diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 60073f8d2b..ce15f319cd 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -680,7 +680,7 @@ void Application::paintGL() { if (whichCamera.getMode() == CAMERA_MODE_MIRROR) { OculusManager::display(whichCamera.getRotation(), whichCamera.getPosition(), whichCamera); } else { - OculusManager::display(_myAvatar->getWorldAlignedOrientation(), whichCamera.getPosition(), whichCamera); + OculusManager::display(_myAvatar->getWorldAlignedOrientation(), _myAvatar->getDefaultEyePosition(), whichCamera); } } else if (TV3DManager::isConnected()) { diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 51f582c4f8..51e21942f1 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -997,6 +997,10 @@ glm::vec3 MyAvatar::getUprightHeadPosition() const { return _position + getWorldAlignedOrientation() * glm::vec3(0.0f, getPelvisToHeadLength(), 0.0f); } +glm::vec3 MyAvatar::getDefaultEyePosition() const { + return _position + getWorldAlignedOrientation() * _skeletonModel.getDefaultEyeModelPosition(); +} + const float SCRIPT_PRIORITY = DEFAULT_PRIORITY + 1.0f; const float RECORDER_PRIORITY = SCRIPT_PRIORITY + 1.0f; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index e38f3f4b2b..10c3e878cc 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -66,6 +66,7 @@ public: const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; } glm::vec3 getGravity() const { return _gravity; } glm::vec3 getUprightHeadPosition() const; + glm::vec3 getDefaultEyePosition() const; bool getShouldRenderLocally() const { return _shouldRender; } const QList& getAnimationHandles() const { return _animationHandles; } diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 86ca42b15e..1af5cfc893 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -27,7 +27,8 @@ SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent) : _owningAvatar(owningAvatar), _boundingShape(), _boundingShapeLocalOffset(0.0f), - _ragdoll(NULL) { + _ragdoll(NULL), + _defaultEyeModelPosition(glm::vec3(0.f, 0.f, 0.f)) { } SkeletonModel::~SkeletonModel() { @@ -470,23 +471,23 @@ bool SkeletonModel::getNeckParentRotationFromDefaultOrientation(glm::quat& neckP return success; } -bool SkeletonModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const { +bool SkeletonModel::getEyeModelPositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const { if (!isActive()) { return false; - } + } const FBXGeometry& geometry = _geometry->getFBXGeometry(); - if (getJointPositionInWorldFrame(geometry.leftEyeJointIndex, firstEyePosition) && - getJointPositionInWorldFrame(geometry.rightEyeJointIndex, secondEyePosition)) { + if (getJointPosition(geometry.leftEyeJointIndex, firstEyePosition) && + getJointPosition(geometry.rightEyeJointIndex, secondEyePosition)) { return true; } // no eye joints; try to estimate based on head/neck joints glm::vec3 neckPosition, headPosition; - if (getJointPositionInWorldFrame(geometry.neckJointIndex, neckPosition) && - getJointPositionInWorldFrame(geometry.headJointIndex, headPosition)) { + if (getJointPosition(geometry.neckJointIndex, neckPosition) && + getJointPosition(geometry.headJointIndex, headPosition)) { const float EYE_PROPORTION = 0.6f; glm::vec3 baseEyePosition = glm::mix(neckPosition, headPosition, EYE_PROPORTION); glm::quat headRotation; - getJointRotationInWorldFrame(geometry.headJointIndex, headRotation); + getJointRotation(geometry.headJointIndex, headRotation); const float EYES_FORWARD = 0.25f; const float EYE_SEPARATION = 0.1f; float headHeight = glm::distance(neckPosition, headPosition); @@ -497,6 +498,15 @@ bool SkeletonModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& seco return false; } +bool SkeletonModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const { + if (getEyeModelPositions(firstEyePosition, secondEyePosition)) { + firstEyePosition = _translation + _rotation * firstEyePosition; + secondEyePosition = _translation + _rotation * secondEyePosition; + return true; + } + return false; +} + void SkeletonModel::renderRagdoll() { if (!_ragdoll) { return; @@ -656,6 +666,20 @@ void SkeletonModel::buildShapes() { // This method moves the shapes to their default positions in Model frame. computeBoundingShape(geometry); + int headJointIndex = _geometry->getFBXGeometry().headJointIndex; + if (0 <= headJointIndex && headJointIndex < _jointStates.size()) { + glm::vec3 leftEyePosition, rightEyePosition; + getEyeModelPositions(leftEyePosition, rightEyePosition); + glm::vec3 midEyePosition = (leftEyePosition + rightEyePosition) / 2.f; + + int rootJointIndex = _geometry->getFBXGeometry().rootJointIndex; + glm::vec3 rootModelPosition; + getJointPosition(rootJointIndex, rootModelPosition); + + _defaultEyeModelPosition = midEyePosition - rootModelPosition; + _defaultEyeModelPosition.z = -_defaultEyeModelPosition.z; + } + // While the shapes are in their default position we disable collisions between // joints that are currently colliding. disableCurrentSelfCollisions(); diff --git a/interface/src/avatar/SkeletonModel.h b/interface/src/avatar/SkeletonModel.h index ca0007ddb4..35122d5e18 100644 --- a/interface/src/avatar/SkeletonModel.h +++ b/interface/src/avatar/SkeletonModel.h @@ -97,6 +97,10 @@ public: /// \return whether or not both eye meshes were found bool getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const; + /// Gets the default position of the mid eye point in model frame coordinates. + /// \return whether or not the head was found. + glm::vec3 getDefaultEyeModelPosition() const { return _defaultEyeModelPosition; } + virtual void updateVisibleJointStates(); SkeletonRagdoll* buildRagdoll(); @@ -140,12 +144,16 @@ private: /// \param position position of joint in model-frame /// \param rotation rotation of joint in model-frame void setHandPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation); + + bool getEyeModelPositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const; Avatar* _owningAvatar; CapsuleShape _boundingShape; glm::vec3 _boundingShapeLocalOffset; SkeletonRagdoll* _ragdoll; + + glm::vec3 _defaultEyeModelPosition; }; #endif // hifi_SkeletonModel_h diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 2031035726..858d8c9239 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -602,6 +602,14 @@ bool Model::getJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) co return true; } +bool Model::getJointRotation(int jointIndex, glm::quat& rotation) const { + if (jointIndex == -1 || jointIndex >= _jointStates.size()) { + return false; + } + rotation = _jointStates[jointIndex].getRotation(); + return true; +} + bool Model::getJointCombinedRotation(int jointIndex, glm::quat& rotation) const { if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return false; diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 89c47e229d..b82db73624 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -148,6 +148,11 @@ public: /// \return true if joint exists bool getJointPosition(int jointIndex, glm::vec3& position) const; + /// \param jointIndex index of joint in model structure + /// \param rotation[out] rotation of joint in model-frame + /// \return true if joint exists + bool getJointRotation(int jointIndex, glm::quat& rotation) const; + QStringList getJointNames() const; AnimationHandlePointer createAnimationHandle();