diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index a6750f820c..c7acfd149a 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -413,7 +413,11 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { } _head.setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll)); - _head.setPosition(_bodyBall[ BODY_BALL_HEAD_BASE ].position); + glm::vec3 headPosition; + if (!_skeletonModel.getHeadPosition(headPosition)) { + headPosition = _bodyBall[BODY_BALL_HEAD_BASE].position; + } + _head.setPosition(headPosition); _head.setSkinColor(glm::vec3(SKIN_COLOR[0], SKIN_COLOR[1], SKIN_COLOR[2])); _head.simulate(deltaTime, false); _skeletonModel.simulate(deltaTime); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 25c202dc45..b7ec4ce4dc 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -318,7 +318,11 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { } _head.setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll)); - _head.setPosition(_bodyBall[ BODY_BALL_HEAD_BASE ].position); + glm::vec3 headPosition; + if (!_skeletonModel.getHeadPosition(headPosition)) { + headPosition = _bodyBall[BODY_BALL_HEAD_BASE].position; + } + _head.setPosition(headPosition); _head.setScale(_scale); _head.setSkinColor(glm::vec3(SKIN_COLOR[0], SKIN_COLOR[1], SKIN_COLOR[2])); _head.simulate(deltaTime, true); diff --git a/interface/src/renderer/FBXReader.cpp b/interface/src/renderer/FBXReader.cpp index 9378bc6ea7..3a2c2607a0 100644 --- a/interface/src/renderer/FBXReader.cpp +++ b/interface/src/renderer/FBXReader.cpp @@ -662,11 +662,13 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) QByteArray jointNeckName = joints.value("jointNeck", "jointNeck").toByteArray(); QByteArray jointRootName = joints.value("jointRoot", "jointRoot").toByteArray(); QByteArray jointLeanName = joints.value("jointLean", "jointLean").toByteArray(); + QByteArray jointHeadName = joints.value("jointHead", "jointHead").toByteArray(); QString jointEyeLeftID; QString jointEyeRightID; QString jointNeckID; QString jointRootID; QString jointLeanID; + QString jointHeadID; QVariantHash blendshapeMappings = mapping.value("bs").toHash(); QHash > blendshapeIndices; @@ -737,6 +739,9 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } else if (name == jointLeanName) { jointLeanID = object.properties.at(0).toString(); + + } else if (name == jointHeadName) { + jointHeadID = object.properties.at(0).toString(); } glm::vec3 translation; glm::vec3 rotationOffset; @@ -965,6 +970,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) geometry.neckJointIndex = modelIDs.indexOf(jointNeckID); geometry.rootJointIndex = modelIDs.indexOf(jointRootID); geometry.leanJointIndex = modelIDs.indexOf(jointLeanID); + geometry.headJointIndex = modelIDs.indexOf(jointHeadID); // extract the translation component of the neck transform if (geometry.neckJointIndex != -1) { diff --git a/interface/src/renderer/FBXReader.h b/interface/src/renderer/FBXReader.h index 9b03f4a475..9f96a67634 100644 --- a/interface/src/renderer/FBXReader.h +++ b/interface/src/renderer/FBXReader.h @@ -111,6 +111,7 @@ public: int neckJointIndex; int rootJointIndex; int leanJointIndex; + int headJointIndex; glm::vec3 neckPivot; }; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 15dcf92e87..8723c6f3b9 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -347,20 +347,17 @@ bool Model::render(float alpha) { return true; } +bool Model::getHeadPosition(glm::vec3& headPosition) const { + return isActive() && getJointPosition(_geometry->getFBXGeometry().headJointIndex, headPosition); +} + bool Model::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const { - if (!isActive() || _jointStates.isEmpty()) { + if (!isActive()) { return false; } const FBXGeometry& geometry = _geometry->getFBXGeometry(); - if (geometry.leftEyeJointIndex != -1) { - const glm::mat4& transform = _jointStates[geometry.leftEyeJointIndex].transform; - firstEyePosition = glm::vec3(transform[3][0], transform[3][1], transform[3][2]); - } - if (geometry.rightEyeJointIndex != -1) { - const glm::mat4& transform = _jointStates[geometry.rightEyeJointIndex].transform; - secondEyePosition = glm::vec3(transform[3][0], transform[3][1], transform[3][2]); - } - return geometry.leftEyeJointIndex != -1 && geometry.rightEyeJointIndex != -1; + return getJointPosition(geometry.leftEyeJointIndex, firstEyePosition) && + getJointPosition(geometry.rightEyeJointIndex, secondEyePosition); } void Model::setURL(const QUrl& url) { @@ -398,6 +395,15 @@ void Model::updateJointState(int index) { } } +bool Model::getJointPosition(int jointIndex, glm::vec3& position) const { + if (jointIndex == -1 || _jointStates.isEmpty()) { + return false; + } + const glm::mat4& transform = _jointStates[jointIndex].transform; + position = glm::vec3(transform[3][0], transform[3][1], transform[3][2]); + return true; +} + void Model::deleteGeometry() { foreach (GLuint id, _blendedVertexBufferIDs) { glDeleteBuffers(1, &id); diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index c84ecac6f3..8ec1df44d2 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -54,6 +54,10 @@ public: Q_INVOKABLE void setURL(const QUrl& url); const QUrl& getURL() const { return _url; } + /// Returns the position of the head joint. + /// \return whether or not the head was found + bool getHeadPosition(glm::vec3& headPosition) const; + /// Retrieve the positions of up to two eye meshes. /// \return whether or not both eye meshes were found bool getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const; @@ -83,6 +87,8 @@ protected: private: + bool getJointPosition(int jointIndex, glm::vec3& position) const; + void deleteGeometry(); float _pupilDilation;