diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 6dc3d820ae..ab4989a651 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1028,7 +1028,28 @@ void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, boo if (!(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) { return; // wait until both models are loaded } - + + Camera *camera = Application::getInstance()->getCamera(); + const glm::vec3 cameraPos = camera->getPosition(); + + // Set near clip distance according to skeleton model dimensions if first person and there is no separate head model. + if (shouldRenderHead(cameraPos, renderMode) || !getHead()->getFaceModel().getURL().isEmpty()) { + renderFrustum->setNearClip(DEFAULT_NEAR_CLIP); + } else { + float clipDistance = _skeletonModel.getHeadClipDistance(); + if (OculusManager::isConnected()) { + // If avatar is horizontally in front of camera, increase clip distance by the amount it is in front. + glm::vec3 cameraToAvatar = _position - cameraPos; + cameraToAvatar.y = 0.0f; + glm::vec3 cameraLookAt = camera->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f); + float headOffset = glm::dot(cameraLookAt, cameraToAvatar); + if (headOffset > 0) { + clipDistance += headOffset; + } + } + renderFrustum->setNearClip(clipDistance); + } + // Render the body's voxels and head Model::RenderMode modelRenderMode = (renderMode == SHADOW_RENDER_MODE) ? Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE; @@ -1040,8 +1061,6 @@ void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, boo } // Render head so long as the camera isn't inside it - const Camera *camera = Application::getInstance()->getCamera(); - const glm::vec3 cameraPos = camera->getPosition(); if (shouldRenderHead(cameraPos, renderMode)) { getHead()->render(1.0f, renderFrustum, modelRenderMode, postLighting); } diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 4fdebd5f6f..3a61f69dee 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -37,7 +37,8 @@ SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent) : _defaultEyeModelPosition(glm::vec3(0.0f, 0.0f, 0.0f)), _standingFoot(NO_FOOT), _standingOffset(0.0f), - _clampedFootPosition(0.0f) + _clampedFootPosition(0.0f), + _headClipDistance(DEFAULT_NEAR_CLIP) { } @@ -78,6 +79,10 @@ void SkeletonModel::setJointStates(QVector states) { buildShapes(); } + Extents meshExtents = getMeshExtents(); + _headClipDistance = -(meshExtents.minimum.z / _scale.z - _defaultEyeModelPosition.z); + _headClipDistance = std::max(_headClipDistance, DEFAULT_NEAR_CLIP); + emit skeletonLoaded(); } diff --git a/interface/src/avatar/SkeletonModel.h b/interface/src/avatar/SkeletonModel.h index 5427fcaf25..298d74fb7a 100644 --- a/interface/src/avatar/SkeletonModel.h +++ b/interface/src/avatar/SkeletonModel.h @@ -110,6 +110,8 @@ public: bool hasSkeleton(); + float getHeadClipDistance() const { return _headClipDistance; } + signals: void skeletonLoaded(); @@ -160,6 +162,8 @@ private: int _standingFoot; glm::vec3 _standingOffset; glm::vec3 _clampedFootPosition; + + float _headClipDistance; // Near clip distance to use if no separate head model }; #endif // hifi_SkeletonModel_h