diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index f4f2a33331..1290cfd53f 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -589,7 +589,7 @@ float VERY_BIG_MASS = 1.0e6f; // virtual void SkeletonModel::buildShapes() { - if (!_geometry || _rootIndex == -1) { + if (_geometry == NULL || _jointStates.isEmpty()) { return; } @@ -743,7 +743,7 @@ void SkeletonModel::resetShapePositionsToDefaultPose() { // Moves shapes to the joint default locations for debug visibility into // how the bounding shape is computed. - if (!_geometry || _rootIndex == -1 || _shapes.isEmpty()) { + if (!_geometry || _shapes.isEmpty()) { // geometry or joints have not yet been created return; } diff --git a/interface/src/renderer/JointState.cpp b/interface/src/renderer/JointState.cpp index 7958e8b6cd..22473d4d39 100644 --- a/interface/src/renderer/JointState.cpp +++ b/interface/src/renderer/JointState.cpp @@ -76,17 +76,22 @@ void JointState::copyState(const JointState& state) { // DO NOT copy _fbxJoint or _constraint } +void JointState::initTransform(const glm::mat4& parentTransform) { + computeTransform(parentTransform); + _positionInParentFrame = glm::inverse(extractRotation(parentTransform)) * (extractTranslation(_transform) - extractTranslation(parentTransform)); +} + void JointState::computeTransform(const glm::mat4& parentTransform) { glm::quat rotationInConstrainedFrame = _fbxJoint->preRotation * _rotationInConstrainedFrame * _fbxJoint->postRotation; - glm::mat4 modifiedTransform = _fbxJoint->preTransform * glm::mat4_cast(rotationInConstrainedFrame) * _fbxJoint->postTransform; - _transform = parentTransform * glm::translate(_fbxJoint->translation) * modifiedTransform; + glm::mat4 rotationInParentFrame = _fbxJoint->preTransform * glm::mat4_cast(rotationInConstrainedFrame) * _fbxJoint->postTransform; + _transform = parentTransform * glm::translate(_fbxJoint->translation) * rotationInParentFrame; _rotation = extractRotation(_transform); } void JointState::computeVisibleTransform(const glm::mat4& parentTransform) { glm::quat rotationInConstrainedFrame = _fbxJoint->preRotation * _visibleRotationInConstrainedFrame * _fbxJoint->postRotation; - glm::mat4 modifiedTransform = _fbxJoint->preTransform * glm::mat4_cast(rotationInConstrainedFrame) * _fbxJoint->postTransform; - _visibleTransform = parentTransform * glm::translate(_fbxJoint->translation) * modifiedTransform; + glm::mat4 rotationInParentFrame = _fbxJoint->preTransform * glm::mat4_cast(rotationInConstrainedFrame) * _fbxJoint->postTransform; + _visibleTransform = parentTransform * glm::translate(_fbxJoint->translation) * rotationInParentFrame; _visibleRotation = extractRotation(_visibleTransform); } diff --git a/interface/src/renderer/JointState.h b/interface/src/renderer/JointState.h index 36a0212b45..c0b08d2cff 100644 --- a/interface/src/renderer/JointState.h +++ b/interface/src/renderer/JointState.h @@ -32,6 +32,7 @@ public: void updateConstraint(); void copyState(const JointState& state); + void initTransform(const glm::mat4& parentTransform); void computeTransform(const glm::mat4& parentTransform); void computeVisibleTransform(const glm::mat4& parentTransform); @@ -98,6 +99,7 @@ private: glm::mat4 _transform; // joint- to model-frame glm::quat _rotation; // joint- to model-frame glm::quat _rotationInConstrainedFrame; // rotation in frame where angular constraints would be applied + glm::vec3 _positionInParentFrame; // only changes when the Model is scaled glm::mat4 _visibleTransform; glm::quat _visibleRotation; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 5fec542c6e..6394cd8c29 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -40,7 +40,6 @@ Model::Model(QObject* parent) : _snapModelToCenter(false), _snappedToCenter(false), _showTrueJointTransforms(true), - _rootIndex(-1), _lodDistance(0.0f), _pupilDilation(0.0f), _url("http://invalid.com") { @@ -126,6 +125,7 @@ void Model::setScaleInternal(const glm::vec3& scale) { const float ONE_PERCENT = 0.01f; if (relativeDeltaScale > ONE_PERCENT || scaleLength < EPSILON) { _scale = scale; + initJointTransforms(); if (_shapes.size() > 0) { clearShapes(); buildShapes(); @@ -165,24 +165,26 @@ QVector Model::createJointStates(const FBXGeometry& geometry) { state.setFBXJoint(&joint); jointStates.append(state); } + return jointStates; +}; +void Model::initJointTransforms() { // compute model transforms - int numJoints = jointStates.size(); + int numJoints = _jointStates.size(); for (int i = 0; i < numJoints; ++i) { - JointState& state = jointStates[i]; + JointState& state = _jointStates[i]; const FBXJoint& joint = state.getFBXJoint(); int parentIndex = joint.parentIndex; if (parentIndex == -1) { - _rootIndex = i; + const FBXGeometry& geometry = _geometry->getFBXGeometry(); // NOTE: in practice geometry.offset has a non-unity scale (rather than a translation) glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset; - state.computeTransform(parentTransform); + state.initTransform(parentTransform); } else { - const JointState& parentState = jointStates.at(parentIndex); - state.computeTransform(parentState.getTransform()); + const JointState& parentState = _jointStates.at(parentIndex); + state.initTransform(parentState.getTransform()); } } - return jointStates; } void Model::init() { @@ -560,6 +562,7 @@ bool Model::updateGeometry() { // virtual void Model::setJointStates(QVector states) { _jointStates = states; + initJointTransforms(); int numJoints = _jointStates.size(); float radius = 0.0f; diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index dde3a68218..078685345b 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -164,7 +164,6 @@ protected: bool _snapModelToCenter; /// is the model's offset automatically adjusted to center around 0,0,0 in model space bool _snappedToCenter; /// are we currently snapped to center bool _showTrueJointTransforms; - int _rootIndex; glm::vec3 _localLightDirections[MAX_LOCAL_LIGHTS]; glm::vec3 _localLightColors[MAX_LOCAL_LIGHTS]; @@ -227,6 +226,7 @@ private: void deleteGeometry(); void renderMeshes(float alpha, RenderMode mode, bool translucent, bool receiveShadows); QVector createJointStates(const FBXGeometry& geometry); + void initJointTransforms(); QSharedPointer _baseGeometry; ///< reference required to prevent collection of base QSharedPointer _nextBaseGeometry;