From 9e60b758df1c24dcd0cd6cde450ec30b91e117a9 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 2 Jun 2014 11:34:59 -0700 Subject: [PATCH 01/29] Made JointState transforms private. Also changed some function names to be more descriptive. Using "Hybrid" to describe frame with world-rotation + model-local-origin. --- interface/src/avatar/Avatar.cpp | 2 +- interface/src/avatar/FaceModel.cpp | 4 +- interface/src/avatar/SkeletonModel.cpp | 14 ++- interface/src/renderer/Model.cpp | 138 ++++++++++++++++++++----- interface/src/renderer/Model.h | 25 ++++- 5 files changed, 144 insertions(+), 39 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 306dc0194e..7850d089e1 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -378,7 +378,7 @@ void Avatar::simulateAttachments(float deltaTime) { model->setLODDistance(getLODDistance()); } if (_skeletonModel.getJointPosition(jointIndex, jointPosition) && - _skeletonModel.getJointRotation(jointIndex, jointRotation)) { + _skeletonModel.getJointRotationInWorldFrame(jointIndex, jointRotation)) { model->setTranslation(jointPosition + jointRotation * attachment.translation * _scale); model->setRotation(jointRotation * attachment.rotation); model->setScale(_skeletonModel.getScale() * attachment.scale); diff --git a/interface/src/avatar/FaceModel.cpp b/interface/src/avatar/FaceModel.cpp index acd3d2c31f..080603ac7e 100644 --- a/interface/src/avatar/FaceModel.cpp +++ b/interface/src/avatar/FaceModel.cpp @@ -49,7 +49,7 @@ void FaceModel::simulate(float deltaTime, bool fullUpdate) { void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) { // get the rotation axes in joint space and use them to adjust the rotation glm::mat3 axes = glm::mat3_cast(_rotation); - glm::mat3 inverse = glm::mat3(glm::inverse(parentState._transform * glm::translate(state.getDefaultTranslationInParentFrame()) * + glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getHybridTransform() * glm::translate(state.getDefaultTranslationInParentFrame()) * joint.preTransform * glm::mat4_cast(joint.preRotation))); state._rotation = glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalRoll(), glm::normalize(inverse * axes[2])) * glm::angleAxis(RADIANS_PER_DEGREE * _owningHead->getFinalYaw(), glm::normalize(inverse * axes[1])) @@ -59,7 +59,7 @@ void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBX void FaceModel::maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) { // likewise with the eye joints - glm::mat4 inverse = glm::inverse(parentState._transform * glm::translate(state.getDefaultTranslationInParentFrame()) * + glm::mat4 inverse = glm::inverse(parentState.getHybridTransform() * glm::translate(state.getDefaultTranslationInParentFrame()) * joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation)); glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getFinalOrientation() * IDENTITY_FRONT, 0.0f)); glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(_owningHead->getLookAtPosition() + diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 19f51d5db7..4c3cc72f37 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -221,9 +221,7 @@ void SkeletonModel::updateJointState(int index) { Model::updateJointState(index); if (index == _geometry->getFBXGeometry().rootJointIndex) { - state._transform[3][0] = 0.0f; - state._transform[3][1] = 0.0f; - state._transform[3][2] = 0.0f; + state.clearTransformTranslation(); } } @@ -233,7 +231,7 @@ void SkeletonModel::maybeUpdateLeanRotation(const JointState& parentState, const } // get the rotation axes in joint space and use them to adjust the rotation glm::mat3 axes = glm::mat3_cast(_rotation); - glm::mat3 inverse = glm::mat3(glm::inverse(parentState._transform * glm::translate(state.getDefaultTranslationInParentFrame()) * + glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getHybridTransform() * glm::translate(state.getDefaultTranslationInParentFrame()) * joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation))); state._rotation = glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanSideways(), glm::normalize(inverse * axes[2])) * glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanForward(), @@ -259,11 +257,11 @@ void SkeletonModel::renderJointConstraints(int jointIndex) { do { const FBXJoint& joint = geometry.joints.at(jointIndex); const JointState& jointState = _jointStates.at(jointIndex); - glm::vec3 position = extractTranslation(jointState._transform) + _translation; + glm::vec3 position = extractTranslation(jointState.getHybridTransform()) + _translation; glPushMatrix(); glTranslatef(position.x, position.y, position.z); - glm::quat parentRotation = (joint.parentIndex == -1) ? _rotation : _jointStates.at(joint.parentIndex)._combinedRotation; + glm::quat parentRotation = (joint.parentIndex == -1) ? _rotation : _rotation * _jointStates.at(joint.parentIndex).getRotationInModelFrame(); glm::vec3 rotationAxis = glm::axis(parentRotation); glRotatef(glm::degrees(glm::angle(parentRotation)), rotationAxis.x, rotationAxis.y, rotationAxis.z); float fanScale = directionSize * 0.75f; @@ -296,7 +294,7 @@ void SkeletonModel::renderJointConstraints(int jointIndex) { } glPopMatrix(); - renderOrientationDirections(position, jointState._combinedRotation, directionSize); + renderOrientationDirections(position, _rotation * jointState.getRotationInModelFrame(), directionSize); jointIndex = joint.parentIndex; } while (jointIndex != -1 && geometry.joints.at(jointIndex).isFree); @@ -416,7 +414,7 @@ bool SkeletonModel::getNeckParentRotation(glm::quat& neckParentRotation) const { if (geometry.neckJointIndex == -1) { return false; } - return getJointRotation(geometry.joints.at(geometry.neckJointIndex).parentIndex, neckParentRotation); + return getJointRotationInWorldFrame(geometry.joints.at(geometry.neckJointIndex).parentIndex, neckParentRotation); } bool SkeletonModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const { diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 0335378a54..be9457a6bf 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -144,11 +144,26 @@ QVector Model::createJointStates(const FBXGeometry& geometry) { jointStates.append(state); } + // compute model transforms + int numJoints = jointStates.size(); + for (int i = 0; i < numJoints; ++i) { + JointState& state = jointStates[i]; + const FBXJoint& joint = state.getFBXJoint(); + int parentIndex = joint.parentIndex; + if (parentIndex == -1) { + _rootIndex = i; + glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset; + state.computeTransformInModelFrame(parentTransform); + } else { + const JointState& parentState = jointStates.at(parentIndex); + state.computeTransformInModelFrame(parentState.getTransformInModelFrame()); + } + } + // compute transforms // Unfortunately, the joints are not neccessarily in order from parents to children, // so we must iterate over the list multiple times until all are set correctly. QVector jointIsSet; - int numJoints = jointStates.size(); jointIsSet.fill(false, numJoints); int numJointsSet = 0; int lastNumJointsSet = -1; @@ -169,7 +184,8 @@ QVector Model::createJointStates(const FBXGeometry& geometry) { jointIsSet[i] = true; } else if (jointIsSet[parentIndex]) { const JointState& parentState = jointStates.at(parentIndex); - state.computeTransforms(parentState._transform, parentState._combinedRotation); + glm::quat parentRotation = _rotation * parentState.getRotationInModelFrame(); + state.computeTransforms(parentState.getHybridTransform(), parentRotation); ++numJointsSet; jointIsSet[i] = true; } @@ -624,11 +640,12 @@ bool Model::getJointPosition(int jointIndex, glm::vec3& position) const { if (jointIndex == -1 || _jointStates.isEmpty()) { return false; } - position = _translation + extractTranslation(_jointStates[jointIndex]._transform); + position = _translation + extractTranslation(_jointStates[jointIndex].getHybridTransform()); + //position = _translation + _rotation * _jointState[jointIndex].getPositionInModelFrame(); return true; } -bool Model::getJointRotation(int jointIndex, glm::quat& rotation, bool fromBind) const { +bool Model::getJointRotationInWorldFrame(int jointIndex, glm::quat& rotation, bool fromBind) const { if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return false; } @@ -848,11 +865,12 @@ void Model::updateShapePositions() { for (int i = 0; i < _jointStates.size(); i++) { const FBXJoint& joint = geometry.joints[i]; // shape position and rotation need to be in world-frame - glm::vec3 jointToShapeOffset = uniformScale * (_jointStates[i]._combinedRotation * joint.shapePosition); - glm::vec3 worldPosition = extractTranslation(_jointStates[i]._transform) + jointToShapeOffset + _translation; + glm::quat rotationInWorldFrame = _rotation * _jointStates[i].getRotationInModelFrame(); + glm::vec3 jointToShapeOffset = uniformScale * (rotationInWorldFrame * joint.shapePosition); + glm::vec3 worldPosition = extractTranslation(_jointStates[i].getHybridTransform()) + jointToShapeOffset + _translation; Shape* shape = _jointShapes[i]; shape->setPosition(worldPosition); - shape->setRotation(_jointStates[i]._combinedRotation * joint.shapeRotation); + shape->setRotation(rotationInWorldFrame * joint.shapeRotation); float distance = glm::distance(worldPosition, _translation) + shape->getBoundingRadius(); if (distance > _boundingRadius) { _boundingRadius = distance; @@ -874,12 +892,12 @@ bool Model::findRayIntersection(const glm::vec3& origin, const glm::vec3& direct float radiusScale = extractUniformScale(_scale); for (int i = 0; i < _jointStates.size(); i++) { const FBXJoint& joint = geometry.joints[i]; - glm::vec3 end = extractTranslation(_jointStates[i]._transform); + glm::vec3 end = extractTranslation(_jointStates[i].getHybridTransform()); float endRadius = joint.boneRadius * radiusScale; glm::vec3 start = end; float startRadius = joint.boneRadius * radiusScale; if (joint.parentIndex != -1) { - start = extractTranslation(_jointStates[joint.parentIndex]._transform); + start = extractTranslation(_jointStates[joint.parentIndex].getHybridTransform()); startRadius = geometry.joints[joint.parentIndex].boneRadius * radiusScale; } // for now, use average of start and end radii @@ -1090,7 +1108,7 @@ void Model::simulateInternal(float deltaTime) { glm::vec3 jointTranslation = _translation; glm::quat jointRotation = _rotation; getJointPosition(attachment.jointIndex, jointTranslation); - getJointRotation(attachment.jointIndex, jointRotation); + getJointRotationInWorldFrame(attachment.jointIndex, jointRotation); model->setTranslation(jointTranslation + jointRotation * attachment.translation * _scale); model->setRotation(jointRotation * attachment.rotation); @@ -1106,7 +1124,7 @@ void Model::simulateInternal(float deltaTime) { const FBXMesh& mesh = geometry.meshes.at(i); for (int j = 0; j < mesh.clusters.size(); j++) { const FBXCluster& cluster = mesh.clusters.at(j); - state.clusterMatrices[j] = _jointStates[cluster.jointIndex]._transform * cluster.inverseBindMatrix; + state.clusterMatrices[j] = _jointStates[cluster.jointIndex].getHybridTransform() * cluster.inverseBindMatrix; } } @@ -1120,13 +1138,26 @@ void Model::updateJointState(int index) { JointState& state = _jointStates[index]; const FBXJoint& joint = state.getFBXJoint(); - if (joint.parentIndex == -1) { + // compute model transforms + int parentIndex = joint.parentIndex; + if (parentIndex == -1) { + const FBXGeometry& geometry = _geometry->getFBXGeometry(); + glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset; + state.computeTransformInModelFrame(parentTransform); + } else { + const JointState& parentState = _jointStates.at(parentIndex); + state.computeTransformInModelFrame(parentState.getTransformInModelFrame()); + } + + // compute hybrid transforms + if (parentIndex == -1) { const FBXGeometry& geometry = _geometry->getFBXGeometry(); glm::mat4 baseTransform = glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset) * geometry.offset; state.computeTransforms(baseTransform, _rotation); } else { - const JointState& parentState = _jointStates.at(joint.parentIndex); - state.computeTransforms(parentState._transform, parentState._combinedRotation); + const JointState& parentState = _jointStates.at(parentIndex); + glm::quat parentRotation = _rotation * parentState.getRotationInModelFrame(); + state.computeTransforms(parentState.getHybridTransform(), parentRotation); } } @@ -1162,7 +1193,7 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const } // then, we go from the joint upwards, rotating the end as close as possible to the target - glm::vec3 endPosition = extractTranslation(_jointStates[jointIndex]._transform); + glm::vec3 endPosition = extractTranslation(_jointStates[jointIndex].getHybridTransform()); for (int j = 1; freeLineage.at(j - 1) != lastFreeIndex; j++) { int index = freeLineage.at(j); JointState& state = _jointStates[index]; @@ -1170,9 +1201,9 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const if (!(joint.isFree || allIntermediatesFree)) { continue; } - glm::vec3 jointPosition = extractTranslation(state._transform); + glm::vec3 jointPosition = extractTranslation(state.getHybridTransform()); glm::vec3 jointVector = endPosition - jointPosition; - glm::quat oldCombinedRotation = state._combinedRotation; + glm::quat oldCombinedRotation = _rotation * state.getRotationInModelFrame(); glm::quat combinedDelta; float combinedWeight; if (useRotation) { @@ -1190,7 +1221,7 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const for (int k = j - 1; k > 0; k--) { int index = freeLineage.at(k); updateJointState(index); - positionSum += extractTranslation(_jointStates.at(index)._transform); + positionSum += extractTranslation(_jointStates.at(index).getHybridTransform()); } glm::vec3 projectedCenterOfMass = glm::cross(jointVector, glm::cross(positionSum / (j - 1.0f) - jointPosition, jointVector)); @@ -1202,7 +1233,7 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const } } state.applyRotationDelta(combinedDelta, true, priority); - glm::quat actualDelta = state._combinedRotation * glm::inverse(oldCombinedRotation); + glm::quat actualDelta = _rotation * state.getRotationInModelFrame() * glm::inverse(oldCombinedRotation); endPosition = actualDelta * jointVector + jointPosition; if (useRotation) { endRotation = actualDelta * endRotation; @@ -1827,6 +1858,11 @@ void AnimationHandle::replaceMatchingPriorities(float newPriority) { } } +glm::mat4 Model::getBaseTransform(const glm::mat4& geometryOffset) const { + //return glm::translate(_translation) * glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset) * geometryOffset; + return glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset) * geometryOffset; +} + // ---------------------------------------------------------------------------- // JointState TODO: move this class to its own files // ---------------------------------------------------------------------------- @@ -1844,23 +1880,44 @@ void JointState::setFBXJoint(const FBXJoint* joint) { void JointState::copyState(const JointState& state) { _rotation = state._rotation; - _transform = state._transform; + + _transformInModelFrame = state._transformInModelFrame; + _rotationInModelFrame = extractRotation(_transformInModelFrame); _combinedRotation = state._combinedRotation; + _transform = state._transform; + _animationPriority = state._animationPriority; // DO NOT copy _fbxJoint } -void JointState::computeTransforms(const glm::mat4& baseTransform, const glm::quat& baseRotation) { +void JointState::computeTransformInModelFrame(const glm::mat4& parentTransform) { + glm::quat modifiedRotation = _fbxJoint->preRotation * _rotation * _fbxJoint->postRotation; + glm::mat4 modifiedTransform = _fbxJoint->preTransform * glm::mat4_cast(modifiedRotation) * _fbxJoint->postTransform; + _transformInModelFrame = parentTransform * glm::translate(_fbxJoint->translation) * modifiedTransform; + _rotationInModelFrame = extractRotation(_transformInModelFrame); +} + +glm::quat JointState::getRotationInWorldFrame(const glm::quat& baseRotation) const { + return baseRotation * _rotationInModelFrame; +} + +glm::vec3 JointState::getPositionInWorldFrame(const glm::quat& baseRotation, const glm::vec3& basePosition) const { + return basePosition + baseRotation * extractTranslation(_transformInModelFrame); +} + +void JointState::computeTransforms(const glm::mat4& parentTransform, const glm::quat& baseRotation) { assert(_fbxJoint != NULL); - glm::quat combinedRotation = _fbxJoint->preRotation * _rotation * _fbxJoint->postRotation; - _transform = baseTransform * glm::translate(_fbxJoint->translation) * _fbxJoint->preTransform - * glm::mat4_cast(combinedRotation) * _fbxJoint->postTransform; - _combinedRotation = baseRotation * combinedRotation; + + glm::quat modifiedRotation = _fbxJoint->preRotation * _rotation * _fbxJoint->postRotation; + glm::mat4 modifiedTransform = _fbxJoint->preTransform * glm::mat4_cast(modifiedRotation) * _fbxJoint->postTransform; + _transform = parentTransform * glm::translate(_fbxJoint->translation) * modifiedTransform; + _combinedRotation = baseRotation * modifiedRotation; } glm::quat JointState::getJointRotation(bool fromBind) const { assert(_fbxJoint != NULL); return _combinedRotation * (fromBind ? _fbxJoint->inverseBindRotation : _fbxJoint->inverseDefaultRotation); + //return _rotationInModelFrame * (fromBind ? _fbxJoint->inverseBindRotation : _fbxJoint->inverseDefaultRotation); } void JointState::restoreRotation(float fraction, float priority) { @@ -1879,6 +1936,15 @@ void JointState::setRotation(const glm::quat& rotation, float priority) { } } +void JointState::clearTransformTranslation() { + _transform[3][0] = 0.0f; + _transform[3][1] = 0.0f; + _transform[3][2] = 0.0f; + _transformInModelFrame[3][0] = 0.0f; + _transformInModelFrame[3][1] = 0.0f; + _transformInModelFrame[3][2] = 0.0f; +} + void JointState::applyRotationDelta(const glm::quat& delta, bool constrain, float priority) { assert(_fbxJoint != NULL); if (priority < _animationPriority) { @@ -1899,6 +1965,28 @@ void JointState::applyRotationDelta(const glm::quat& delta, bool constrain, floa _rotation = newRotation; } +/* +void JointState::applyRotationDelta(const glm::quat& delta, bool constrain, float priority) { + assert(_fbxJoint != NULL); + if (priority < _animationPriority) { + return; + } + _animationPriority = priority; + if (!constrain || (_fbxJoint->rotationMin == glm::vec3(-PI, -PI, -PI) && + _fbxJoint->rotationMax == glm::vec3(PI, PI, PI))) { + // no constraints + _rotation = _rotation * glm::inverse(_rotationInModelFrame) * delta * _rotationInModelFrame; + _rotationInModelFrame = delta * _rotationInModelFrame; + return; + } + glm::quat targetRotation = delta * _rotationInModelFrame; + glm::vec3 eulers = safeEulerAngles(_rotation * glm::inverse(_rotationInModelFrame) * targetRotation); + glm::quat newRotation = glm::quat(glm::clamp(eulers, _fbxJoint->rotationMin, _fbxJoint->rotationMax)); + _rotationInModelFrame = _rotationInModelFrame * glm::inverse(_rotation) * newRotation; + _rotation = newRotation; +} +*/ + const glm::vec3& JointState::getDefaultTranslationInParentFrame() const { assert(_fbxJoint != NULL); return _fbxJoint->translation; diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 6e38c7eed4..26229a4a34 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -40,6 +40,15 @@ public: void copyState(const JointState& state); + void computeTransformInModelFrame(const glm::mat4& parentTransform); + const glm::mat4& getTransformInModelFrame() const { return _transformInModelFrame; } + + glm::quat getRotationInModelFrame() const { return _rotationInModelFrame; } + glm::vec3 getPositionInModelFrame() const { return extractTranslation(_transformInModelFrame); } + + glm::quat getRotationInWorldFrame(const glm::quat& baseRotation) const; + glm::vec3 getPositionInWorldFrame(const glm::quat& baseRotation, const glm::vec3& basePosition) const; + /// computes new _transform and _combinedRotation void computeTransforms(const glm::mat4& baseTransform, const glm::quat& baseRotation); @@ -54,14 +63,22 @@ public: /// \param rotation is from bind- to world-frame /// computes parent relative _rotation and sets that + /// \warning no combined transforms are updated! void setRotation(const glm::quat& rotation, float priority); + const glm::mat4& getHybridTransform() const { return _transform; } + const glm::quat& getRotationInWorldFrame() const { return _combinedRotation; } + void clearTransformTranslation(); + glm::quat _rotation; // rotation relative to parent - glm::mat4 _transform; // rotation to world frame + translation in model frame - glm::quat _combinedRotation; // rotation from joint local to world frame float _animationPriority; // the priority of the animation affecting this joint private: + glm::mat4 _transformInModelFrame; + glm::quat _rotationInModelFrame; + glm::quat _combinedRotation; // rotation from joint local to world frame + glm::mat4 _transform; // rotation to world frame + translation in model frame + const FBXJoint* _fbxJoint; // JointState does NOT own its FBXJoint }; @@ -156,7 +173,7 @@ public: int getLastFreeJointIndex(int jointIndex) const; bool getJointPosition(int jointIndex, glm::vec3& position) const; - bool getJointRotation(int jointIndex, glm::quat& rotation, bool fromBind = false) const; + bool getJointRotationInWorldFrame(int jointIndex, glm::quat& rotation, bool fromBind = false) const; QStringList getJointNames() const; @@ -199,6 +216,8 @@ public: const CapsuleShape& getBoundingShape() const { return _boundingShape; } + glm::mat4 getBaseTransform(const glm::mat4& geometryOffset) const; + protected: QSharedPointer _geometry; From 9b3773fa3b7e3729cc25eb0cf321102d19ee0736 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 2 Jun 2014 14:20:13 -0700 Subject: [PATCH 02/29] remove 'fromBind' argument to getJointRotation() --- interface/src/avatar/SkeletonModel.cpp | 6 +++--- interface/src/renderer/Model.cpp | 16 ++++++++-------- interface/src/renderer/Model.h | 6 +++--- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index d347e39d2c..48efbdc4dc 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -147,7 +147,7 @@ void SkeletonModel::applyHandPosition(int jointIndex, const glm::vec3& position) return; } JointState& state = _jointStates[jointIndex]; - glm::quat handRotation = state.getJointRotation(true); + glm::quat handRotation = state.getJointRotation(); // align hand with forearm float sign = (jointIndex == geometry.rightHandJointIndex) ? 1.0f : -1.0f; @@ -170,10 +170,10 @@ void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) { if (!Menu::getInstance()->isOptionChecked(MenuOption::AlternateIK) && Menu::getInstance()->isOptionChecked(MenuOption::AlignForearmsWithWrists)) { JointState parentState = _jointStates[parentJointIndex]; - palmRotation = parentState.getJointRotation(true); + palmRotation = parentState.getJointRotation(); } else { JointState state = _jointStates[jointIndex]; - palmRotation = state.getJointRotation(true); + palmRotation = state.getJointRotation(); } palmRotation = rotationBetween(palmRotation * geometry.palmDirection, palm.getNormal()) * palmRotation; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index d809909dfe..3a3adfc8cc 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -756,11 +756,11 @@ bool Model::getJointPosition(int jointIndex, glm::vec3& position) const { return true; } -bool Model::getJointRotationInWorldFrame(int jointIndex, glm::quat& rotation, bool fromBind) const { +bool Model::getJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const { if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return false; } - rotation = _jointStates[jointIndex].getJointRotation(fromBind); + rotation = _jointStates[jointIndex].getJointRotation(); return true; } @@ -768,7 +768,7 @@ bool Model::getJointCombinedRotation(int jointIndex, glm::quat& rotation) const if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return false; } - rotation = _jointStates[jointIndex].getRotationInWorldFrame(); + rotation = _jointStates[jointIndex].getRotationInWorldFrame(_rotation); return true; } @@ -1306,9 +1306,9 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const JointState& state = _jointStates[jointIndex]; // TODO: figure out what this is trying to do and combine it into one JointState method - endRotation = state.getJointRotation(true); + endRotation = state.getJointRotation(); state.applyRotationDelta(rotation * glm::inverse(endRotation), true, priority); - endRotation = state.getJointRotation(true); + endRotation = state.getJointRotation(); } // then, we go from the joint upwards, rotating the end as close as possible to the target @@ -2067,10 +2067,10 @@ void JointState::computeTransforms(const glm::mat4& parentTransform, const glm:: _combinedRotation = baseRotation * modifiedRotation; } -glm::quat JointState::getJointRotation(bool fromBind) const { +glm::quat JointState::getJointRotation() const { assert(_fbxJoint != NULL); - return _combinedRotation * (fromBind ? _fbxJoint->inverseBindRotation : _fbxJoint->inverseDefaultRotation); - //return _rotationInModelFrame * (fromBind ? _fbxJoint->inverseBindRotation : _fbxJoint->inverseDefaultRotation); + return _combinedRotation * _fbxJoint->inverseBindRotation; + //return _rotationInModelFrame * _fbxJoint->inverseBindRotation; } void JointState::restoreRotation(float fraction, float priority) { diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index b7d089e713..b6ae6c9012 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -53,7 +53,7 @@ public: void computeTransforms(const glm::mat4& baseTransform, const glm::quat& baseRotation); /// \return rotation from the joint's default (or bind) frame to world frame - glm::quat getJointRotation(bool fromBind = false) const; + glm::quat getJointRotation() const; void applyRotationDelta(const glm::quat& delta, bool constrain = true, float priority = 1.0f); @@ -67,7 +67,7 @@ public: void setRotation(const glm::quat& rotation, float priority); const glm::mat4& getHybridTransform() const { return _transform; } - const glm::quat& getRotationInWorldFrame() const { return _combinedRotation; } + //const glm::quat& getRotationInWorldFrame() const { return _combinedRotation; } void clearTransformTranslation(); glm::quat _rotation; // rotation relative to parent @@ -173,7 +173,7 @@ public: int getLastFreeJointIndex(int jointIndex) const; bool getJointPosition(int jointIndex, glm::vec3& position) const; - bool getJointRotationInWorldFrame(int jointIndex, glm::quat& rotation, bool fromBind = false) const; + bool getJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const; bool getJointCombinedRotation(int jointIndex, glm::quat& rotation) const; QStringList getJointNames() const; From d7be5faa9d902f8826456bf5105d8c90a3bab0dd Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 2 Jun 2014 14:43:25 -0700 Subject: [PATCH 03/29] unravel rotation code by giving proper names The goal is: eliminate dependency on JointState::_combinedRotation (which is joint-to-world) and store joint-to-model transforms instead --- interface/src/avatar/SkeletonModel.cpp | 10 +++++----- interface/src/renderer/Model.cpp | 16 +++++++--------- interface/src/renderer/Model.h | 6 +++--- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 48efbdc4dc..de9c413017 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -147,7 +147,7 @@ void SkeletonModel::applyHandPosition(int jointIndex, const glm::vec3& position) return; } JointState& state = _jointStates[jointIndex]; - glm::quat handRotation = state.getJointRotation(); + glm::quat handRotation = state.getRotationFromBindToModelFrame(); // align hand with forearm float sign = (jointIndex == geometry.rightHandJointIndex) ? 1.0f : -1.0f; @@ -170,10 +170,10 @@ void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) { if (!Menu::getInstance()->isOptionChecked(MenuOption::AlternateIK) && Menu::getInstance()->isOptionChecked(MenuOption::AlignForearmsWithWrists)) { JointState parentState = _jointStates[parentJointIndex]; - palmRotation = parentState.getJointRotation(); + palmRotation = parentState.getRotationFromBindToModelFrame(); } else { JointState state = _jointStates[jointIndex]; - palmRotation = state.getJointRotation(); + palmRotation = state.getRotationFromBindToModelFrame(); } palmRotation = rotationBetween(palmRotation * geometry.palmDirection, palm.getNormal()) * palmRotation; @@ -414,7 +414,7 @@ bool SkeletonModel::getNeckParentRotation(glm::quat& neckParentRotation) const { if (geometry.neckJointIndex == -1) { return false; } - return getJointRotationInWorldFrame(geometry.joints.at(geometry.neckJointIndex).parentIndex, neckParentRotation); + return getJointRotationFromBindToWorldFrame(geometry.joints.at(geometry.neckJointIndex).parentIndex, neckParentRotation); } bool SkeletonModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const { @@ -433,7 +433,7 @@ bool SkeletonModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& seco const float EYE_PROPORTION = 0.6f; glm::vec3 baseEyePosition = glm::mix(neckPosition, headPosition, EYE_PROPORTION); glm::quat headRotation; - getJointRotationInWorldFrame(geometry.headJointIndex, headRotation); + getJointRotationFromBindToWorldFrame(geometry.headJointIndex, headRotation); const float EYES_FORWARD = 0.25f; const float EYE_SEPARATION = 0.1f; float headHeight = glm::distance(neckPosition, headPosition); diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 3a3adfc8cc..11cd4678e3 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -756,11 +756,11 @@ bool Model::getJointPosition(int jointIndex, glm::vec3& position) const { return true; } -bool Model::getJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const { +bool Model::getJointRotationFromBindToWorldFrame(int jointIndex, glm::quat& rotation) const { if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return false; } - rotation = _jointStates[jointIndex].getJointRotation(); + rotation = _rotation * _jointStates[jointIndex].getRotationFromBindToModelFrame(); return true; } @@ -1227,7 +1227,7 @@ void Model::simulateInternal(float deltaTime) { glm::vec3 jointTranslation = _translation; glm::quat jointRotation = _rotation; getJointPosition(attachment.jointIndex, jointTranslation); - getJointRotationInWorldFrame(attachment.jointIndex, jointRotation); + getJointRotationFromBindToWorldFrame(attachment.jointIndex, jointRotation); model->setTranslation(jointTranslation + jointRotation * attachment.translation * _scale); model->setRotation(jointRotation * attachment.rotation); @@ -1306,9 +1306,9 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const JointState& state = _jointStates[jointIndex]; // TODO: figure out what this is trying to do and combine it into one JointState method - endRotation = state.getJointRotation(); + endRotation = _rotation * state.getRotationFromBindToModelFrame(); state.applyRotationDelta(rotation * glm::inverse(endRotation), true, priority); - endRotation = state.getJointRotation(); + endRotation = _rotation * state.getRotationFromBindToModelFrame(); } // then, we go from the joint upwards, rotating the end as close as possible to the target @@ -2067,10 +2067,8 @@ void JointState::computeTransforms(const glm::mat4& parentTransform, const glm:: _combinedRotation = baseRotation * modifiedRotation; } -glm::quat JointState::getJointRotation() const { - assert(_fbxJoint != NULL); - return _combinedRotation * _fbxJoint->inverseBindRotation; - //return _rotationInModelFrame * _fbxJoint->inverseBindRotation; +glm::quat JointState::getRotationFromBindToModelFrame() const { + return _rotationInModelFrame * _fbxJoint->inverseBindRotation; } void JointState::restoreRotation(float fraction, float priority) { diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index b6ae6c9012..2577953a3a 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -52,8 +52,8 @@ public: /// computes new _transform and _combinedRotation void computeTransforms(const glm::mat4& baseTransform, const glm::quat& baseRotation); - /// \return rotation from the joint's default (or bind) frame to world frame - glm::quat getJointRotation() const; + /// \return rotation that moves a vector given in this joint's bind-frame to the model-frame + glm::quat getRotationFromBindToModelFrame() const; void applyRotationDelta(const glm::quat& delta, bool constrain = true, float priority = 1.0f); @@ -173,7 +173,7 @@ public: int getLastFreeJointIndex(int jointIndex) const; bool getJointPosition(int jointIndex, glm::vec3& position) const; - bool getJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const; + bool getJointRotationFromBindToWorldFrame(int jointIndex, glm::quat& rotation) const; bool getJointCombinedRotation(int jointIndex, glm::quat& rotation) const; QStringList getJointNames() const; From f99489c157814968ec948bf54c4e93378f0fdfaa Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 3 Jun 2014 10:40:30 -0700 Subject: [PATCH 04/29] rolling back previous change for IK instability --- interface/src/avatar/SkeletonModel.cpp | 10 +++++----- interface/src/renderer/Model.cpp | 15 ++++++++------- interface/src/renderer/Model.h | 6 +++--- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index de9c413017..48efbdc4dc 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -147,7 +147,7 @@ void SkeletonModel::applyHandPosition(int jointIndex, const glm::vec3& position) return; } JointState& state = _jointStates[jointIndex]; - glm::quat handRotation = state.getRotationFromBindToModelFrame(); + glm::quat handRotation = state.getJointRotation(); // align hand with forearm float sign = (jointIndex == geometry.rightHandJointIndex) ? 1.0f : -1.0f; @@ -170,10 +170,10 @@ void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) { if (!Menu::getInstance()->isOptionChecked(MenuOption::AlternateIK) && Menu::getInstance()->isOptionChecked(MenuOption::AlignForearmsWithWrists)) { JointState parentState = _jointStates[parentJointIndex]; - palmRotation = parentState.getRotationFromBindToModelFrame(); + palmRotation = parentState.getJointRotation(); } else { JointState state = _jointStates[jointIndex]; - palmRotation = state.getRotationFromBindToModelFrame(); + palmRotation = state.getJointRotation(); } palmRotation = rotationBetween(palmRotation * geometry.palmDirection, palm.getNormal()) * palmRotation; @@ -414,7 +414,7 @@ bool SkeletonModel::getNeckParentRotation(glm::quat& neckParentRotation) const { if (geometry.neckJointIndex == -1) { return false; } - return getJointRotationFromBindToWorldFrame(geometry.joints.at(geometry.neckJointIndex).parentIndex, neckParentRotation); + return getJointRotationInWorldFrame(geometry.joints.at(geometry.neckJointIndex).parentIndex, neckParentRotation); } bool SkeletonModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const { @@ -433,7 +433,7 @@ bool SkeletonModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& seco const float EYE_PROPORTION = 0.6f; glm::vec3 baseEyePosition = glm::mix(neckPosition, headPosition, EYE_PROPORTION); glm::quat headRotation; - getJointRotationFromBindToWorldFrame(geometry.headJointIndex, headRotation); + getJointRotationInWorldFrame(geometry.headJointIndex, headRotation); const float EYES_FORWARD = 0.25f; const float EYE_SEPARATION = 0.1f; float headHeight = glm::distance(neckPosition, headPosition); diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 11cd4678e3..e3be11c5d2 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -756,11 +756,11 @@ bool Model::getJointPosition(int jointIndex, glm::vec3& position) const { return true; } -bool Model::getJointRotationFromBindToWorldFrame(int jointIndex, glm::quat& rotation) const { +bool Model::getJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const { if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return false; } - rotation = _rotation * _jointStates[jointIndex].getRotationFromBindToModelFrame(); + rotation = _jointStates[jointIndex].getJointRotation(); return true; } @@ -1227,7 +1227,7 @@ void Model::simulateInternal(float deltaTime) { glm::vec3 jointTranslation = _translation; glm::quat jointRotation = _rotation; getJointPosition(attachment.jointIndex, jointTranslation); - getJointRotationFromBindToWorldFrame(attachment.jointIndex, jointRotation); + getJointRotationInWorldFrame(attachment.jointIndex, jointRotation); model->setTranslation(jointTranslation + jointRotation * attachment.translation * _scale); model->setRotation(jointRotation * attachment.rotation); @@ -1306,9 +1306,9 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const JointState& state = _jointStates[jointIndex]; // TODO: figure out what this is trying to do and combine it into one JointState method - endRotation = _rotation * state.getRotationFromBindToModelFrame(); + endRotation = state.getJointRotation(); state.applyRotationDelta(rotation * glm::inverse(endRotation), true, priority); - endRotation = _rotation * state.getRotationFromBindToModelFrame(); + endRotation = state.getJointRotation(); } // then, we go from the joint upwards, rotating the end as close as possible to the target @@ -2067,8 +2067,9 @@ void JointState::computeTransforms(const glm::mat4& parentTransform, const glm:: _combinedRotation = baseRotation * modifiedRotation; } -glm::quat JointState::getRotationFromBindToModelFrame() const { - return _rotationInModelFrame * _fbxJoint->inverseBindRotation; +glm::quat JointState::getJointRotation() const { + assert(_fbxJoint != NULL); + return _combinedRotation * _fbxJoint->inverseBindRotation; } void JointState::restoreRotation(float fraction, float priority) { diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 2577953a3a..b6ae6c9012 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -52,8 +52,8 @@ public: /// computes new _transform and _combinedRotation void computeTransforms(const glm::mat4& baseTransform, const glm::quat& baseRotation); - /// \return rotation that moves a vector given in this joint's bind-frame to the model-frame - glm::quat getRotationFromBindToModelFrame() const; + /// \return rotation from the joint's default (or bind) frame to world frame + glm::quat getJointRotation() const; void applyRotationDelta(const glm::quat& delta, bool constrain = true, float priority = 1.0f); @@ -173,7 +173,7 @@ public: int getLastFreeJointIndex(int jointIndex) const; bool getJointPosition(int jointIndex, glm::vec3& position) const; - bool getJointRotationFromBindToWorldFrame(int jointIndex, glm::quat& rotation) const; + bool getJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const; bool getJointCombinedRotation(int jointIndex, glm::quat& rotation) const; QStringList getJointNames() const; From 03bf1fe69df74167d514e62de551a572589457bf Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 3 Jun 2014 14:04:09 -0700 Subject: [PATCH 05/29] Add joint manipulations in model-frame --- interface/src/avatar/SkeletonModel.cpp | 121 ++++++++++++++++++++++++- interface/src/avatar/SkeletonModel.h | 2 + interface/src/renderer/Model.cpp | 112 ++++++++++++++++++++++- interface/src/renderer/Model.h | 9 ++ 4 files changed, 238 insertions(+), 6 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 48efbdc4dc..1f2f502b44 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -73,8 +73,8 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { restoreLeftHandPosition(HAND_RESTORATION_RATE, PALM_PRIORITY); } else { - applyPalmData(geometry.leftHandJointIndex, hand->getPalms()[leftPalmIndex]); - applyPalmData(geometry.rightHandJointIndex, hand->getPalms()[rightPalmIndex]); + applyPalmDataInModelFrame(geometry.leftHandJointIndex, hand->getPalms()[leftPalmIndex]); + applyPalmDataInModelFrame(geometry.rightHandJointIndex, hand->getPalms()[rightPalmIndex]); } } @@ -194,13 +194,64 @@ void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) { parentState.setRotation(palmRotation, PALM_PRIORITY); // slam parent-relative rotation to identity _jointStates[jointIndex]._rotation = glm::quat(); - } else { setJointPosition(jointIndex, palm.getPosition(), palmRotation, true, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY); } } +void SkeletonModel::applyPalmDataInModelFrame(int jointIndex, PalmData& palm) { + if (jointIndex == -1 || jointIndex >= _jointStates.size()) { + return; + } + const FBXGeometry& geometry = _geometry->getFBXGeometry(); + float sign = (jointIndex == geometry.rightHandJointIndex) ? 1.0f : -1.0f; + int parentJointIndex = geometry.joints.at(jointIndex).parentIndex; + if (parentJointIndex == -1) { + return; + } + + // rotate palm to align with its normal (normal points out of hand's palm) + glm::quat palmRotation; + glm::quat r0, r1; + if (!Menu::getInstance()->isOptionChecked(MenuOption::AlternateIK) && + Menu::getInstance()->isOptionChecked(MenuOption::AlignForearmsWithWrists)) { + JointState parentState = _jointStates[parentJointIndex]; + palmRotation = parentState.getRotationFromBindToModelFrame(); + r0 = palmRotation; + } else { + JointState state = _jointStates[jointIndex]; + palmRotation = state.getRotationFromBindToModelFrame(); + } + glm::quat inverseRotation = glm::inverse(_rotation); + glm::vec3 palmNormal = inverseRotation * palm.getNormal(); + palmRotation = rotationBetween(palmRotation * geometry.palmDirection, palmNormal) * palmRotation; + r1 = palmRotation; + + // rotate palm to align with finger direction + glm::vec3 direction = inverseRotation * palm.getFingerDirection(); + palmRotation = rotationBetween(palmRotation * glm::vec3(-sign, 0.0f, 0.0f), direction) * palmRotation; + + // set hand position, rotation + glm::vec3 palmPosition = inverseRotation * (palm.getPosition() - _translation); + if (Menu::getInstance()->isOptionChecked(MenuOption::AlternateIK)) { + setHandPositionInModelFrame(jointIndex, palmPosition, palmRotation); + + } else if (Menu::getInstance()->isOptionChecked(MenuOption::AlignForearmsWithWrists)) { + glm::vec3 forearmVector = palmRotation * glm::vec3(sign, 0.0f, 0.0f); + setJointPositionInModelFrame(parentJointIndex, palmPosition + forearmVector * + geometry.joints.at(jointIndex).distanceToParent * extractUniformScale(_scale), + glm::quat(), false, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY); + JointState& parentState = _jointStates[parentJointIndex]; + parentState.setRotationInModelFrame(palmRotation, PALM_PRIORITY); + // slam parent-relative rotation to identity + _jointStates[jointIndex]._rotation = glm::quat(); + } else { + setJointPositionInModelFrame(jointIndex, palmPosition, palmRotation, + true, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY); + } +} + void SkeletonModel::updateJointState(int index) { JointState& state = _jointStates[index]; const FBXJoint& joint = state.getFBXJoint(); @@ -365,6 +416,70 @@ void SkeletonModel::setHandPosition(int jointIndex, const glm::vec3& position, c JointState& handState = _jointStates[jointIndex]; handState.setRotation(rotation, PALM_PRIORITY); } + +void SkeletonModel::setHandPositionInModelFrame(int jointIndex, const glm::vec3& position, const glm::quat& rotation) { + // this algorithm is from sample code from sixense + const FBXGeometry& geometry = _geometry->getFBXGeometry(); + int elbowJointIndex = geometry.joints.at(jointIndex).parentIndex; + if (elbowJointIndex == -1) { + return; + } + int shoulderJointIndex = geometry.joints.at(elbowJointIndex).parentIndex; + glm::vec3 shoulderPosition; + if (!getJointPositionInModelFrame(shoulderJointIndex, shoulderPosition)) { + return; + } + // precomputed lengths + float scale = extractUniformScale(_scale); + float upperArmLength = geometry.joints.at(elbowJointIndex).distanceToParent * scale; + float lowerArmLength = geometry.joints.at(jointIndex).distanceToParent * scale; + + // first set wrist position + glm::vec3 wristPosition = position; + + glm::vec3 shoulderToWrist = wristPosition - shoulderPosition; + float distanceToWrist = glm::length(shoulderToWrist); + + // prevent gimbal lock + if (distanceToWrist > upperArmLength + lowerArmLength - EPSILON) { + distanceToWrist = upperArmLength + lowerArmLength - EPSILON; + shoulderToWrist = glm::normalize(shoulderToWrist) * distanceToWrist; + wristPosition = shoulderPosition + shoulderToWrist; + } + + // cosine of angle from upper arm to hand vector + float cosA = (upperArmLength * upperArmLength + distanceToWrist * distanceToWrist - lowerArmLength * lowerArmLength) / + (2 * upperArmLength * distanceToWrist); + float mid = upperArmLength * cosA; + float height = sqrt(upperArmLength * upperArmLength + mid * mid - 2 * upperArmLength * mid * cosA); + + // direction of the elbow + glm::vec3 handNormal = glm::cross(rotation * glm::vec3(0.0f, 1.0f, 0.0f), shoulderToWrist); // elbow rotating with wrist + glm::vec3 relaxedNormal = glm::cross(glm::vec3(0.0f, 1.0f, 0.0f), shoulderToWrist); // elbow pointing straight down + const float NORMAL_WEIGHT = 0.5f; + glm::vec3 finalNormal = glm::mix(relaxedNormal, handNormal, NORMAL_WEIGHT); + + bool rightHand = (jointIndex == geometry.rightHandJointIndex); + if (rightHand ? (finalNormal.y > 0.0f) : (finalNormal.y < 0.0f)) { + finalNormal.y = 0.0f; // dont allow elbows to point inward (y is vertical axis) + } + + glm::vec3 tangent = glm::normalize(glm::cross(shoulderToWrist, finalNormal)); + + // ik solution + glm::vec3 elbowPosition = shoulderPosition + glm::normalize(shoulderToWrist) * mid - tangent * height; + glm::vec3 forwardVector(rightHand ? -1.0f : 1.0f, 0.0f, 0.0f); + glm::quat shoulderRotation = rotationBetween(forwardVector, elbowPosition - shoulderPosition); + + JointState& shoulderState = _jointStates[shoulderJointIndex]; + shoulderState.setRotationInModelFrame(shoulderRotation, PALM_PRIORITY); + + JointState& elbowState = _jointStates[elbowJointIndex]; + elbowState.setRotationInModelFrame(rotationBetween(shoulderRotation * forwardVector, wristPosition - elbowPosition) * shoulderRotation, PALM_PRIORITY); + + JointState& handState = _jointStates[jointIndex]; + handState.setRotationInModelFrame(rotation, PALM_PRIORITY); +} bool SkeletonModel::getLeftHandPosition(glm::vec3& position) const { return getJointPosition(getLeftHandJointIndex(), position); diff --git a/interface/src/avatar/SkeletonModel.h b/interface/src/avatar/SkeletonModel.h index 91070e4ad6..183ba899b8 100644 --- a/interface/src/avatar/SkeletonModel.h +++ b/interface/src/avatar/SkeletonModel.h @@ -94,6 +94,7 @@ protected: void applyHandPosition(int jointIndex, const glm::vec3& position); void applyPalmData(int jointIndex, PalmData& palm); + void applyPalmDataInModelFrame(int jointIndex, PalmData& palm); /// Updates the state of the joint at the specified index. virtual void updateJointState(int index); @@ -106,6 +107,7 @@ private: void renderJointConstraints(int jointIndex); void setHandPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation); + void setHandPositionInModelFrame(int jointIndex, const glm::vec3& position, const glm::quat& rotation); Avatar* _owningAvatar; }; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index e3be11c5d2..2616ded481 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -756,6 +756,14 @@ bool Model::getJointPosition(int jointIndex, glm::vec3& position) const { return true; } +bool Model::getJointPositionInModelFrame(int jointIndex, glm::vec3& position) const { + if (jointIndex == -1 || jointIndex >= _jointStates.size()) { + return false; + } + position = extractTranslation(_jointStates[jointIndex].getTransformInModelFrame()); + return true; +} + bool Model::getJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const { if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return false; @@ -1369,6 +1377,94 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const return true; } +bool Model::setJointPositionInModelFrame(int jointIndex, const glm::vec3& position, const glm::quat& rotation, bool useRotation, + int lastFreeIndex, bool allIntermediatesFree, const glm::vec3& alignment, float priority) { + if (jointIndex == -1 || _jointStates.isEmpty()) { + return false; + } + const FBXGeometry& geometry = _geometry->getFBXGeometry(); + const QVector& freeLineage = geometry.joints.at(jointIndex).freeLineage; + if (freeLineage.isEmpty()) { + return false; + } + if (lastFreeIndex == -1) { + lastFreeIndex = freeLineage.last(); + } + + // this is a cyclic coordinate descent algorithm: see + // http://www.ryanjuckett.com/programming/animation/21-cyclic-coordinate-descent-in-2d + const int ITERATION_COUNT = 1; + glm::vec3 worldAlignment = alignment; + for (int i = 0; i < ITERATION_COUNT; i++) { + // first, try to rotate the end effector as close as possible to the target rotation, if any + glm::quat endRotation; + if (useRotation) { + JointState& state = _jointStates[jointIndex]; + + // TODO: figure out what this is trying to do and combine it into one JointState method + endRotation = state.getJointRotation(); + state.applyRotationDelta(rotation * glm::inverse(endRotation), true, priority); + endRotation = state.getJointRotation(); + } + + // then, we go from the joint upwards, rotating the end as close as possible to the target + glm::vec3 endPosition = extractTranslation(_jointStates[jointIndex].getTransformInModelFrame()); + for (int j = 1; freeLineage.at(j - 1) != lastFreeIndex; j++) { + int index = freeLineage.at(j); + JointState& state = _jointStates[index]; + const FBXJoint& joint = state.getFBXJoint(); + if (!(joint.isFree || allIntermediatesFree)) { + continue; + } + glm::vec3 jointPosition = extractTranslation(state.getTransformInModelFrame()); + glm::vec3 jointVector = endPosition - jointPosition; + glm::quat oldCombinedRotation = state.getRotationInModelFrame(); + glm::quat combinedDelta; + float combinedWeight; + if (useRotation) { + combinedDelta = safeMix(rotation * glm::inverse(endRotation), + rotationBetween(jointVector, position - jointPosition), 0.5f); + combinedWeight = 2.0f; + + } else { + combinedDelta = rotationBetween(jointVector, position - jointPosition); + combinedWeight = 1.0f; + } + if (alignment != glm::vec3() && j > 1) { + jointVector = endPosition - jointPosition; + glm::vec3 positionSum; + for (int k = j - 1; k > 0; k--) { + int index = freeLineage.at(k); + updateJointState(index); + positionSum += extractTranslation(_jointStates.at(index).getTransformInModelFrame()); + } + glm::vec3 projectedCenterOfMass = glm::cross(jointVector, + glm::cross(positionSum / (j - 1.0f) - jointPosition, jointVector)); + glm::vec3 projectedAlignment = glm::cross(jointVector, glm::cross(worldAlignment, jointVector)); + const float LENGTH_EPSILON = 0.001f; + if (glm::length(projectedCenterOfMass) > LENGTH_EPSILON && glm::length(projectedAlignment) > LENGTH_EPSILON) { + combinedDelta = safeMix(combinedDelta, rotationBetween(projectedCenterOfMass, projectedAlignment), + 1.0f / (combinedWeight + 1.0f)); + } + } + state.applyRotationDeltaInModelFrame(combinedDelta, true, priority); + glm::quat actualDelta = state.getRotationInModelFrame() * glm::inverse(oldCombinedRotation); + endPosition = actualDelta * jointVector + jointPosition; + if (useRotation) { + endRotation = actualDelta * endRotation; + } + } + } + + // now update the joint states from the top + for (int j = freeLineage.size() - 1; j >= 0; j--) { + updateJointState(freeLineage.at(j)); + } + _shapesAreDirty = true; + + return true; +} + bool Model::restoreJointPosition(int jointIndex, float fraction, float priority) { if (jointIndex == -1 || _jointStates.isEmpty()) { return false; @@ -2072,6 +2168,10 @@ glm::quat JointState::getJointRotation() const { return _combinedRotation * _fbxJoint->inverseBindRotation; } +glm::quat JointState::getRotationFromBindToModelFrame() const { + return _rotationInModelFrame * _fbxJoint->inverseBindRotation; +} + void JointState::restoreRotation(float fraction, float priority) { assert(_fbxJoint != NULL); if (priority == _animationPriority) { @@ -2088,6 +2188,14 @@ void JointState::setRotation(const glm::quat& rotation, float priority) { } } +void JointState::setRotationInModelFrame(const glm::quat& rotation, float priority) { + assert(_fbxJoint != NULL); + if (priority >= _animationPriority) { + _rotation = _rotation * glm::inverse(_rotationInModelFrame) * rotation * glm::inverse(_fbxJoint->inverseBindRotation); + _animationPriority = priority; + } +} + void JointState::clearTransformTranslation() { _transform[3][0] = 0.0f; _transform[3][1] = 0.0f; @@ -2117,8 +2225,7 @@ void JointState::applyRotationDelta(const glm::quat& delta, bool constrain, floa _rotation = newRotation; } -/* -void JointState::applyRotationDelta(const glm::quat& delta, bool constrain, float priority) { +void JointState::applyRotationDeltaInModelFrame(const glm::quat& delta, bool constrain, float priority) { assert(_fbxJoint != NULL); if (priority < _animationPriority) { return; @@ -2137,7 +2244,6 @@ void JointState::applyRotationDelta(const glm::quat& delta, bool constrain, floa _rotationInModelFrame = _rotationInModelFrame * glm::inverse(_rotation) * newRotation; _rotation = newRotation; } -*/ const glm::vec3& JointState::getDefaultTranslationInParentFrame() const { assert(_fbxJoint != NULL); diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index b6ae6c9012..37f0ffbc60 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -54,8 +54,10 @@ public: /// \return rotation from the joint's default (or bind) frame to world frame glm::quat getJointRotation() const; + glm::quat getRotationFromBindToModelFrame() const; void applyRotationDelta(const glm::quat& delta, bool constrain = true, float priority = 1.0f); + void applyRotationDeltaInModelFrame(const glm::quat& delta, bool constrain = true, float priority = 1.0f); const glm::vec3& getDefaultTranslationInParentFrame() const; @@ -65,6 +67,7 @@ public: /// computes parent relative _rotation and sets that /// \warning no combined transforms are updated! void setRotation(const glm::quat& rotation, float priority); + void setRotationInModelFrame(const glm::quat& rotation, float priority); const glm::mat4& getHybridTransform() const { return _transform; } //const glm::quat& getRotationInWorldFrame() const { return _combinedRotation; } @@ -176,6 +179,8 @@ public: bool getJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const; bool getJointCombinedRotation(int jointIndex, glm::quat& rotation) const; + bool getJointPositionInModelFrame(int jointIndex, glm::vec3& position) const; + QStringList getJointNames() const; AnimationHandlePointer createAnimationHandle(); @@ -266,6 +271,10 @@ protected: bool setJointPosition(int jointIndex, const glm::vec3& translation, const glm::quat& rotation = glm::quat(), bool useRotation = false, int lastFreeIndex = -1, bool allIntermediatesFree = false, const glm::vec3& alignment = glm::vec3(0.0f, -1.0f, 0.0f), float priority = 1.0f); + + bool setJointPositionInModelFrame(int jointIndex, const glm::vec3& translation, const glm::quat& rotation = glm::quat(), + bool useRotation = false, int lastFreeIndex = -1, bool allIntermediatesFree = false, + const glm::vec3& alignment = glm::vec3(0.0f, -1.0f, 0.0f), float priority = 1.0f); /// Restores the indexed joint to its default position. /// \param fraction the fraction of the default position to apply (i.e., 0.25f to slerp one fourth of the way to From 05af9932621fc604a79a6840055d1a91bd97e049 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 3 Jun 2014 14:24:04 -0700 Subject: [PATCH 06/29] Add more model-frame methods --- interface/src/avatar/SkeletonModel.cpp | 26 +++++++++++++++++++++++++- interface/src/avatar/SkeletonModel.h | 1 + 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 1f2f502b44..8a3082d89a 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -63,7 +63,8 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { if (_owningAvatar->getHandState() == HAND_STATE_NULL) { restoreRightHandPosition(HAND_RESTORATION_RATE, PALM_PRIORITY); } else { - applyHandPosition(geometry.rightHandJointIndex, _owningAvatar->getHandPosition()); + glm::vec3 handPosition = glm::inverse(_rotation) * (_owningAvatar->getHandPosition() - _translation); + applyHandPositionInModelFrame(geometry.rightHandJointIndex, handPosition); } restoreLeftHandPosition(HAND_RESTORATION_RATE, PALM_PRIORITY); @@ -154,6 +155,29 @@ void SkeletonModel::applyHandPosition(int jointIndex, const glm::vec3& position) state.applyRotationDelta(rotationBetween(handRotation * glm::vec3(-sign, 0.0f, 0.0f), forearmVector), true, PALM_PRIORITY); } +void SkeletonModel::applyHandPositionInModelFrame(int jointIndex, const glm::vec3& position) { + if (jointIndex == -1 || jointIndex >= _jointStates.size()) { + return; + } + setJointPositionInModelFrame(jointIndex, position, glm::quat(), false, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY); + + const FBXGeometry& geometry = _geometry->getFBXGeometry(); + glm::vec3 handPosition, elbowPosition; + getJointPositionInModelFrame(jointIndex, handPosition); + getJointPositionInModelFrame(geometry.joints.at(jointIndex).parentIndex, elbowPosition); + glm::vec3 forearmVector = handPosition - elbowPosition; + float forearmLength = glm::length(forearmVector); + if (forearmLength < EPSILON) { + return; + } + JointState& state = _jointStates[jointIndex]; + glm::quat handRotation = state.getRotationInModelFrame(); + + // align hand with forearm + float sign = (jointIndex == geometry.rightHandJointIndex) ? 1.0f : -1.0f; + state.applyRotationDeltaInModelFrame(rotationBetween(handRotation * glm::vec3(-sign, 0.0f, 0.0f), forearmVector), true, PALM_PRIORITY); +} + void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) { if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return; diff --git a/interface/src/avatar/SkeletonModel.h b/interface/src/avatar/SkeletonModel.h index 183ba899b8..5447027d96 100644 --- a/interface/src/avatar/SkeletonModel.h +++ b/interface/src/avatar/SkeletonModel.h @@ -92,6 +92,7 @@ public: protected: void applyHandPosition(int jointIndex, const glm::vec3& position); + void applyHandPositionInModelFrame(int jointIndex, const glm::vec3& position); void applyPalmData(int jointIndex, PalmData& palm); void applyPalmDataInModelFrame(int jointIndex, PalmData& palm); From e7f32c211bfb3ea802cc13c2673d886ab50852e4 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 3 Jun 2014 14:48:57 -0700 Subject: [PATCH 07/29] remove world-frame hand/palm set methods --- interface/src/avatar/SkeletonModel.cpp | 135 +------------------------ interface/src/avatar/SkeletonModel.h | 3 - interface/src/renderer/Model.cpp | 94 +---------------- interface/src/renderer/Model.h | 5 +- 4 files changed, 5 insertions(+), 232 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 8a3082d89a..4c2c80d11a 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -70,7 +70,7 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { } else if (leftPalmIndex == rightPalmIndex) { // right hand only - applyPalmData(geometry.rightHandJointIndex, hand->getPalms()[leftPalmIndex]); + applyPalmDataInModelFrame(geometry.rightHandJointIndex, hand->getPalms()[leftPalmIndex]); restoreLeftHandPosition(HAND_RESTORATION_RATE, PALM_PRIORITY); } else { @@ -132,29 +132,6 @@ bool operator<(const IndexValue& firstIndex, const IndexValue& secondIndex) { return firstIndex.value < secondIndex.value; } -void SkeletonModel::applyHandPosition(int jointIndex, const glm::vec3& position) { - if (jointIndex == -1 || jointIndex >= _jointStates.size()) { - return; - } - setJointPosition(jointIndex, position, glm::quat(), false, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY); - - const FBXGeometry& geometry = _geometry->getFBXGeometry(); - glm::vec3 handPosition, elbowPosition; - getJointPosition(jointIndex, handPosition); - getJointPosition(geometry.joints.at(jointIndex).parentIndex, elbowPosition); - glm::vec3 forearmVector = handPosition - elbowPosition; - float forearmLength = glm::length(forearmVector); - if (forearmLength < EPSILON) { - return; - } - JointState& state = _jointStates[jointIndex]; - glm::quat handRotation = state.getJointRotation(); - - // align hand with forearm - float sign = (jointIndex == geometry.rightHandJointIndex) ? 1.0f : -1.0f; - state.applyRotationDelta(rotationBetween(handRotation * glm::vec3(-sign, 0.0f, 0.0f), forearmVector), true, PALM_PRIORITY); -} - void SkeletonModel::applyHandPositionInModelFrame(int jointIndex, const glm::vec3& position) { if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return; @@ -178,52 +155,6 @@ void SkeletonModel::applyHandPositionInModelFrame(int jointIndex, const glm::vec state.applyRotationDeltaInModelFrame(rotationBetween(handRotation * glm::vec3(-sign, 0.0f, 0.0f), forearmVector), true, PALM_PRIORITY); } -void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) { - if (jointIndex == -1 || jointIndex >= _jointStates.size()) { - return; - } - const FBXGeometry& geometry = _geometry->getFBXGeometry(); - float sign = (jointIndex == geometry.rightHandJointIndex) ? 1.0f : -1.0f; - int parentJointIndex = geometry.joints.at(jointIndex).parentIndex; - if (parentJointIndex == -1) { - return; - } - - // rotate palm to align with its normal (normal points out of hand's palm) - glm::quat palmRotation; - if (!Menu::getInstance()->isOptionChecked(MenuOption::AlternateIK) && - Menu::getInstance()->isOptionChecked(MenuOption::AlignForearmsWithWrists)) { - JointState parentState = _jointStates[parentJointIndex]; - palmRotation = parentState.getJointRotation(); - } else { - JointState state = _jointStates[jointIndex]; - palmRotation = state.getJointRotation(); - } - palmRotation = rotationBetween(palmRotation * geometry.palmDirection, palm.getNormal()) * palmRotation; - - // rotate palm to align with finger direction - glm::vec3 direction = palm.getFingerDirection(); - palmRotation = rotationBetween(palmRotation * glm::vec3(-sign, 0.0f, 0.0f), direction) * palmRotation; - - // set hand position, rotation - if (Menu::getInstance()->isOptionChecked(MenuOption::AlternateIK)) { - setHandPosition(jointIndex, palm.getPosition(), palmRotation); - - } else if (Menu::getInstance()->isOptionChecked(MenuOption::AlignForearmsWithWrists)) { - glm::vec3 forearmVector = palmRotation * glm::vec3(sign, 0.0f, 0.0f); - setJointPosition(parentJointIndex, palm.getPosition() + forearmVector * - geometry.joints.at(jointIndex).distanceToParent * extractUniformScale(_scale), - glm::quat(), false, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY); - JointState& parentState = _jointStates[parentJointIndex]; - parentState.setRotation(palmRotation, PALM_PRIORITY); - // slam parent-relative rotation to identity - _jointStates[jointIndex]._rotation = glm::quat(); - } else { - setJointPosition(jointIndex, palm.getPosition(), palmRotation, - true, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY); - } -} - void SkeletonModel::applyPalmDataInModelFrame(int jointIndex, PalmData& palm) { if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return; @@ -377,70 +308,6 @@ void SkeletonModel::renderJointConstraints(int jointIndex) { glLineWidth(1.0f); } -void SkeletonModel::setHandPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation) { - // this algorithm is from sample code from sixense - const FBXGeometry& geometry = _geometry->getFBXGeometry(); - int elbowJointIndex = geometry.joints.at(jointIndex).parentIndex; - if (elbowJointIndex == -1) { - return; - } - int shoulderJointIndex = geometry.joints.at(elbowJointIndex).parentIndex; - glm::vec3 shoulderPosition; - if (!getJointPosition(shoulderJointIndex, shoulderPosition)) { - return; - } - // precomputed lengths - float scale = extractUniformScale(_scale); - float upperArmLength = geometry.joints.at(elbowJointIndex).distanceToParent * scale; - float lowerArmLength = geometry.joints.at(jointIndex).distanceToParent * scale; - - // first set wrist position - glm::vec3 wristPosition = position; - - glm::vec3 shoulderToWrist = wristPosition - shoulderPosition; - float distanceToWrist = glm::length(shoulderToWrist); - - // prevent gimbal lock - if (distanceToWrist > upperArmLength + lowerArmLength - EPSILON) { - distanceToWrist = upperArmLength + lowerArmLength - EPSILON; - shoulderToWrist = glm::normalize(shoulderToWrist) * distanceToWrist; - wristPosition = shoulderPosition + shoulderToWrist; - } - - // cosine of angle from upper arm to hand vector - float cosA = (upperArmLength * upperArmLength + distanceToWrist * distanceToWrist - lowerArmLength * lowerArmLength) / - (2 * upperArmLength * distanceToWrist); - float mid = upperArmLength * cosA; - float height = sqrt(upperArmLength * upperArmLength + mid * mid - 2 * upperArmLength * mid * cosA); - - // direction of the elbow - glm::vec3 handNormal = glm::cross(rotation * glm::vec3(0.0f, 1.0f, 0.0f), shoulderToWrist); // elbow rotating with wrist - glm::vec3 relaxedNormal = glm::cross(glm::vec3(0.0f, 1.0f, 0.0f), shoulderToWrist); // elbow pointing straight down - const float NORMAL_WEIGHT = 0.5f; - glm::vec3 finalNormal = glm::mix(relaxedNormal, handNormal, NORMAL_WEIGHT); - - bool rightHand = (jointIndex == geometry.rightHandJointIndex); - if (rightHand ? (finalNormal.y > 0.0f) : (finalNormal.y < 0.0f)) { - finalNormal.y = 0.0f; // dont allow elbows to point inward (y is vertical axis) - } - - glm::vec3 tangent = glm::normalize(glm::cross(shoulderToWrist, finalNormal)); - - // ik solution - glm::vec3 elbowPosition = shoulderPosition + glm::normalize(shoulderToWrist) * mid - tangent * height; - glm::vec3 forwardVector(rightHand ? -1.0f : 1.0f, 0.0f, 0.0f); - glm::quat shoulderRotation = rotationBetween(forwardVector, elbowPosition - shoulderPosition); - - JointState& shoulderState = _jointStates[shoulderJointIndex]; - shoulderState.setRotation(shoulderRotation, PALM_PRIORITY); - - JointState& elbowState = _jointStates[elbowJointIndex]; - elbowState.setRotation(rotationBetween(shoulderRotation * forwardVector, wristPosition - elbowPosition) * shoulderRotation, PALM_PRIORITY); - - JointState& handState = _jointStates[jointIndex]; - handState.setRotation(rotation, PALM_PRIORITY); -} - void SkeletonModel::setHandPositionInModelFrame(int jointIndex, const glm::vec3& position, const glm::quat& rotation) { // this algorithm is from sample code from sixense const FBXGeometry& geometry = _geometry->getFBXGeometry(); diff --git a/interface/src/avatar/SkeletonModel.h b/interface/src/avatar/SkeletonModel.h index 5447027d96..092722fd40 100644 --- a/interface/src/avatar/SkeletonModel.h +++ b/interface/src/avatar/SkeletonModel.h @@ -91,10 +91,8 @@ public: protected: - void applyHandPosition(int jointIndex, const glm::vec3& position); void applyHandPositionInModelFrame(int jointIndex, const glm::vec3& position); - void applyPalmData(int jointIndex, PalmData& palm); void applyPalmDataInModelFrame(int jointIndex, PalmData& palm); /// Updates the state of the joint at the specified index. @@ -107,7 +105,6 @@ protected: private: void renderJointConstraints(int jointIndex); - void setHandPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation); void setHandPositionInModelFrame(int jointIndex, const glm::vec3& position, const glm::quat& rotation); Avatar* _owningAvatar; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 2616ded481..65c9f1e691 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1288,95 +1288,6 @@ void Model::updateJointState(int index) { } } -bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const glm::quat& rotation, bool useRotation, - int lastFreeIndex, bool allIntermediatesFree, const glm::vec3& alignment, float priority) { - if (jointIndex == -1 || _jointStates.isEmpty()) { - return false; - } - glm::vec3 relativePosition = translation - _translation; - const FBXGeometry& geometry = _geometry->getFBXGeometry(); - const QVector& freeLineage = geometry.joints.at(jointIndex).freeLineage; - if (freeLineage.isEmpty()) { - return false; - } - if (lastFreeIndex == -1) { - lastFreeIndex = freeLineage.last(); - } - - // this is a cyclic coordinate descent algorithm: see - // http://www.ryanjuckett.com/programming/animation/21-cyclic-coordinate-descent-in-2d - const int ITERATION_COUNT = 1; - glm::vec3 worldAlignment = _rotation * alignment; - for (int i = 0; i < ITERATION_COUNT; i++) { - // first, try to rotate the end effector as close as possible to the target rotation, if any - glm::quat endRotation; - if (useRotation) { - JointState& state = _jointStates[jointIndex]; - - // TODO: figure out what this is trying to do and combine it into one JointState method - endRotation = state.getJointRotation(); - state.applyRotationDelta(rotation * glm::inverse(endRotation), true, priority); - endRotation = state.getJointRotation(); - } - - // then, we go from the joint upwards, rotating the end as close as possible to the target - glm::vec3 endPosition = extractTranslation(_jointStates[jointIndex].getHybridTransform()); - for (int j = 1; freeLineage.at(j - 1) != lastFreeIndex; j++) { - int index = freeLineage.at(j); - JointState& state = _jointStates[index]; - const FBXJoint& joint = state.getFBXJoint(); - if (!(joint.isFree || allIntermediatesFree)) { - continue; - } - glm::vec3 jointPosition = extractTranslation(state.getHybridTransform()); - glm::vec3 jointVector = endPosition - jointPosition; - glm::quat oldCombinedRotation = _rotation * state.getRotationInModelFrame(); - glm::quat combinedDelta; - float combinedWeight; - if (useRotation) { - combinedDelta = safeMix(rotation * glm::inverse(endRotation), - rotationBetween(jointVector, relativePosition - jointPosition), 0.5f); - combinedWeight = 2.0f; - - } else { - combinedDelta = rotationBetween(jointVector, relativePosition - jointPosition); - combinedWeight = 1.0f; - } - if (alignment != glm::vec3() && j > 1) { - jointVector = endPosition - jointPosition; - glm::vec3 positionSum; - for (int k = j - 1; k > 0; k--) { - int index = freeLineage.at(k); - updateJointState(index); - positionSum += extractTranslation(_jointStates.at(index).getHybridTransform()); - } - glm::vec3 projectedCenterOfMass = glm::cross(jointVector, - glm::cross(positionSum / (j - 1.0f) - jointPosition, jointVector)); - glm::vec3 projectedAlignment = glm::cross(jointVector, glm::cross(worldAlignment, jointVector)); - const float LENGTH_EPSILON = 0.001f; - if (glm::length(projectedCenterOfMass) > LENGTH_EPSILON && glm::length(projectedAlignment) > LENGTH_EPSILON) { - combinedDelta = safeMix(combinedDelta, rotationBetween(projectedCenterOfMass, projectedAlignment), - 1.0f / (combinedWeight + 1.0f)); - } - } - state.applyRotationDelta(combinedDelta, true, priority); - glm::quat actualDelta = _rotation * state.getRotationInModelFrame() * glm::inverse(oldCombinedRotation); - endPosition = actualDelta * jointVector + jointPosition; - if (useRotation) { - endRotation = actualDelta * endRotation; - } - } - } - - // now update the joint states from the top - for (int j = freeLineage.size() - 1; j >= 0; j--) { - updateJointState(freeLineage.at(j)); - } - _shapesAreDirty = true; - - return true; -} - bool Model::setJointPositionInModelFrame(int jointIndex, const glm::vec3& position, const glm::quat& rotation, bool useRotation, int lastFreeIndex, bool allIntermediatesFree, const glm::vec3& alignment, float priority) { if (jointIndex == -1 || _jointStates.isEmpty()) { @@ -1614,9 +1525,10 @@ void Model::applyCollision(CollisionInfo& collision) { axis = glm::normalize(axis); glm::vec3 end; getJointPosition(jointIndex, end); - glm::vec3 newEnd = start + glm::angleAxis(angle, axis) * (end - start); + // transform into model-frame + glm::vec3 newEnd = glm::inverse(_rotation) * (start + glm::angleAxis(angle, axis) * (end - start) - _translation); // try to move it - setJointPosition(jointIndex, newEnd, glm::quat(), false, -1, true); + setJointPositionInModelFrame(jointIndex, newEnd, glm::quat(), false, -1, true); } } } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 37f0ffbc60..31d59d7c3e 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -176,6 +176,7 @@ public: int getLastFreeJointIndex(int jointIndex) const; bool getJointPosition(int jointIndex, glm::vec3& position) const; + bool getJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const; bool getJointCombinedRotation(int jointIndex, glm::quat& rotation) const; @@ -268,10 +269,6 @@ protected: /// Updates the state of the joint at the specified index. virtual void updateJointState(int index); - bool setJointPosition(int jointIndex, const glm::vec3& translation, const glm::quat& rotation = glm::quat(), - bool useRotation = false, int lastFreeIndex = -1, bool allIntermediatesFree = false, - const glm::vec3& alignment = glm::vec3(0.0f, -1.0f, 0.0f), float priority = 1.0f); - bool setJointPositionInModelFrame(int jointIndex, const glm::vec3& translation, const glm::quat& rotation = glm::quat(), bool useRotation = false, int lastFreeIndex = -1, bool allIntermediatesFree = false, const glm::vec3& alignment = glm::vec3(0.0f, -1.0f, 0.0f), float priority = 1.0f); From 7f46e9d514931310bef6a18b850caba80a5ba5d5 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 3 Jun 2014 15:42:38 -0700 Subject: [PATCH 08/29] remove JointState::getJointRotation() (use getRotationModelFrame() instead) --- interface/src/avatar/SkeletonModel.cpp | 2 +- interface/src/renderer/Model.cpp | 13 ++++--------- interface/src/renderer/Model.h | 3 +-- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 4c2c80d11a..8b229590fd 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -199,7 +199,7 @@ void SkeletonModel::applyPalmDataInModelFrame(int jointIndex, PalmData& palm) { glm::quat(), false, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY); JointState& parentState = _jointStates[parentJointIndex]; parentState.setRotationInModelFrame(palmRotation, PALM_PRIORITY); - // slam parent-relative rotation to identity + // lock hand to forearm by slamming its rotation (in parent-frame) to identity _jointStates[jointIndex]._rotation = glm::quat(); } else { setJointPositionInModelFrame(jointIndex, palmPosition, palmRotation, diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 65c9f1e691..626b66ed99 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -768,7 +768,7 @@ bool Model::getJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) co if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return false; } - rotation = _jointStates[jointIndex].getJointRotation(); + rotation = _rotation * _jointStates[jointIndex].getRotationInModelFrame(); return true; } @@ -1313,9 +1313,9 @@ bool Model::setJointPositionInModelFrame(int jointIndex, const glm::vec3& positi JointState& state = _jointStates[jointIndex]; // TODO: figure out what this is trying to do and combine it into one JointState method - endRotation = state.getJointRotation(); - state.applyRotationDelta(rotation * glm::inverse(endRotation), true, priority); - endRotation = state.getJointRotation(); + endRotation = state.getRotationInModelFrame(); + state.applyRotationDeltaInModelFrame(rotation * glm::inverse(endRotation), true, priority); + endRotation = state.getRotationInModelFrame(); } // then, we go from the joint upwards, rotating the end as close as possible to the target @@ -2075,11 +2075,6 @@ void JointState::computeTransforms(const glm::mat4& parentTransform, const glm:: _combinedRotation = baseRotation * modifiedRotation; } -glm::quat JointState::getJointRotation() const { - assert(_fbxJoint != NULL); - return _combinedRotation * _fbxJoint->inverseBindRotation; -} - glm::quat JointState::getRotationFromBindToModelFrame() const { return _rotationInModelFrame * _fbxJoint->inverseBindRotation; } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 31d59d7c3e..7e4f60816b 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -52,8 +52,7 @@ public: /// computes new _transform and _combinedRotation void computeTransforms(const glm::mat4& baseTransform, const glm::quat& baseRotation); - /// \return rotation from the joint's default (or bind) frame to world frame - glm::quat getJointRotation() const; + /// \return rotation from bind to model frame glm::quat getRotationFromBindToModelFrame() const; void applyRotationDelta(const glm::quat& delta, bool constrain = true, float priority = 1.0f); From a1afcfd42c7cceff3741780cb7eedbb95bb3bc3f Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 3 Jun 2014 15:57:16 -0700 Subject: [PATCH 09/29] remove JointState::applyRotationDelta() (use JointState::applyRotationDeltaInModelFrame()) instead) --- interface/src/renderer/Model.cpp | 20 -------------------- interface/src/renderer/Model.h | 1 - 2 files changed, 21 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 626b66ed99..a345a32707 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -2112,26 +2112,6 @@ void JointState::clearTransformTranslation() { _transformInModelFrame[3][2] = 0.0f; } -void JointState::applyRotationDelta(const glm::quat& delta, bool constrain, float priority) { - assert(_fbxJoint != NULL); - if (priority < _animationPriority) { - return; - } - _animationPriority = priority; - if (!constrain || (_fbxJoint->rotationMin == glm::vec3(-PI, -PI, -PI) && - _fbxJoint->rotationMax == glm::vec3(PI, PI, PI))) { - // no constraints - _rotation = _rotation * glm::inverse(_combinedRotation) * delta * _combinedRotation; - _combinedRotation = delta * _combinedRotation; - return; - } - glm::quat targetRotation = delta * _combinedRotation; - glm::vec3 eulers = safeEulerAngles(_rotation * glm::inverse(_combinedRotation) * targetRotation); - glm::quat newRotation = glm::quat(glm::clamp(eulers, _fbxJoint->rotationMin, _fbxJoint->rotationMax)); - _combinedRotation = _combinedRotation * glm::inverse(_rotation) * newRotation; - _rotation = newRotation; -} - void JointState::applyRotationDeltaInModelFrame(const glm::quat& delta, bool constrain, float priority) { assert(_fbxJoint != NULL); if (priority < _animationPriority) { diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 7e4f60816b..eb5b4cd7c8 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -55,7 +55,6 @@ public: /// \return rotation from bind to model frame glm::quat getRotationFromBindToModelFrame() const; - void applyRotationDelta(const glm::quat& delta, bool constrain = true, float priority = 1.0f); void applyRotationDeltaInModelFrame(const glm::quat& delta, bool constrain = true, float priority = 1.0f); const glm::vec3& getDefaultTranslationInParentFrame() const; From d3f51fe38e0ed3f6a7b77e461557bc373fccf5fc Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 4 Jun 2014 10:41:17 -0700 Subject: [PATCH 10/29] FinalOrientation -> FinalOrientationInWorldFrame --- interface/src/Application.cpp | 3 ++- interface/src/Audio.cpp | 2 +- interface/src/AudioReflector.cpp | 2 +- interface/src/avatar/Head.cpp | 9 ++++++--- interface/src/avatar/Head.h | 8 ++++++-- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0e731fde79..10201c5c88 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1841,7 +1841,8 @@ void Application::updateMyAvatarLookAtPosition() { } } else { // I am not looking at anyone else, so just look forward - lookAtSpot = _myAvatar->getHead()->calculateAverageEyePosition() + (_myAvatar->getHead()->getFinalOrientation() * glm::vec3(0.f, 0.f, -TREE_SCALE)); + lookAtSpot = _myAvatar->getHead()->calculateAverageEyePosition() + + (_myAvatar->getHead()->getFinalOrientationInWorldFrame() * glm::vec3(0.f, 0.f, -TREE_SCALE)); } // TODO: Add saccade to mouse pointer when stable, IF not looking at someone (since we know we are looking at it) /* diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 50ab720450..ea93d78a25 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -603,7 +603,7 @@ void Audio::handleAudioInput() { if (audioMixer && audioMixer->getActiveSocket()) { MyAvatar* interfaceAvatar = Application::getInstance()->getAvatar(); glm::vec3 headPosition = interfaceAvatar->getHead()->getPosition(); - glm::quat headOrientation = interfaceAvatar->getHead()->getFinalOrientation(); + glm::quat headOrientation = interfaceAvatar->getHead()->getFinalOrientationInWorldFrame(); // we need the amount of bytes in the buffer + 1 for type // + 12 for 3 floats for position + float for bearing + 1 attenuation byte diff --git a/interface/src/AudioReflector.cpp b/interface/src/AudioReflector.cpp index 52d23b4fee..e18a0ad36e 100644 --- a/interface/src/AudioReflector.cpp +++ b/interface/src/AudioReflector.cpp @@ -459,7 +459,7 @@ void AudioReflector::calculateAllReflections() { // only recalculate when we've moved, or if the attributes have changed // TODO: what about case where new voxels are added in front of us??? bool wantHeadOrientation = Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingHeadOriented); - glm::quat orientation = wantHeadOrientation ? _myAvatar->getHead()->getFinalOrientation() : _myAvatar->getOrientation(); + glm::quat orientation = wantHeadOrientation ? _myAvatar->getHead()->getFinalOrientationInWorldFrame() : _myAvatar->getOrientation(); glm::vec3 origin = _myAvatar->getHead()->getPosition(); glm::vec3 listenerPosition = _myAvatar->getHead()->getPosition(); diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 6f09007b31..ee242d179a 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -188,9 +188,12 @@ void Head::setScale (float scale) { _scale = scale; } -glm::quat Head::getFinalOrientation() const { - return _owningAvatar->getOrientation() * glm::quat(glm::radians( - glm::vec3(getFinalPitch(), getFinalYaw(), getFinalRoll() ))); +glm::quat Head::getFinalOrientationInWorldFrame() const { + return _owningAvatar->getOrientation() * getFinalOrientationInLocalFrame(); +} + +glm::quat Head::getFinalOrientationInLocalFrame() const { + return glm::quat(glm::radians(glm::vec3(getFinalPitch(), getFinalYaw(), getFinalRoll() ))); } glm::quat Head::getCameraOrientation () const { diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index cd7abeb9de..36df51fa6f 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -50,9 +50,13 @@ public: void setRenderLookatVectors(bool onOff) { _renderLookatVectors = onOff; } void setLeanSideways(float leanSideways) { _leanSideways = leanSideways; } void setLeanForward(float leanForward) { _leanForward = leanForward; } + + /// \return orientationBase+Delta + glm::quat getFinalOrientationInLocalFrame() const; - /// \return orientationBody * orientationBase+Delta - glm::quat getFinalOrientation() const; + /// \return orientationBody * (orientationBase+Delta) + glm::quat getFinalOrientationInWorldFrame() const; + /// \return orientationBody * orientationBasePitch glm::quat getCameraOrientation () const; From 14e782e4391c3ff10dc309d4ff5f65ce5d913417 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 4 Jun 2014 10:42:04 -0700 Subject: [PATCH 11/29] remove some JointState::getHybridTransform() calls --- interface/src/avatar/FaceModel.cpp | 12 +++++++----- interface/src/avatar/MyAvatar.cpp | 5 +++-- interface/src/avatar/SkeletonModel.cpp | 6 +++--- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/interface/src/avatar/FaceModel.cpp b/interface/src/avatar/FaceModel.cpp index 080603ac7e..4fb2faf5cf 100644 --- a/interface/src/avatar/FaceModel.cpp +++ b/interface/src/avatar/FaceModel.cpp @@ -48,8 +48,8 @@ void FaceModel::simulate(float deltaTime, bool fullUpdate) { void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) { // get the rotation axes in joint space and use them to adjust the rotation - glm::mat3 axes = glm::mat3_cast(_rotation); - glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getHybridTransform() * glm::translate(state.getDefaultTranslationInParentFrame()) * + glm::mat3 axes = glm::mat3_cast(glm::quat()); + glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getTransformInModelFrame() * glm::translate(state.getDefaultTranslationInParentFrame()) * joint.preTransform * glm::mat4_cast(joint.preRotation))); state._rotation = glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalRoll(), glm::normalize(inverse * axes[2])) * glm::angleAxis(RADIANS_PER_DEGREE * _owningHead->getFinalYaw(), glm::normalize(inverse * axes[1])) @@ -59,9 +59,11 @@ void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBX void FaceModel::maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) { // likewise with the eye joints - glm::mat4 inverse = glm::inverse(parentState.getHybridTransform() * glm::translate(state.getDefaultTranslationInParentFrame()) * - joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation)); - glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getFinalOrientation() * IDENTITY_FRONT, 0.0f)); + // NOTE: at the moment we do the math in the world-frame, hence the inverse transform is more complex than usual. + glm::mat4 inverse = glm::inverse(glm::mat4_cast(_rotation) * parentState.getTransformInModelFrame() * + glm::translate(state.getDefaultTranslationInParentFrame()) * + joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation)); + glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getFinalOrientationInWorldFrame() * IDENTITY_FRONT, 0.0f)); glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(_owningHead->getLookAtPosition() + _owningHead->getSaccade() - _translation, 1.0f)); glm::quat between = rotationBetween(front, lookAt); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index c13950e520..f761729417 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -236,7 +236,7 @@ void MyAvatar::updateFromTrackers(float deltaTime) { estimatedRotation = glm::degrees(safeEulerAngles(tracker->getHeadRotation())); } } - + // Rotate the body if the head is turned beyond the screen if (Menu::getInstance()->isOptionChecked(MenuOption::TurnWithHead)) { const float TRACKER_YAW_TURN_SENSITIVITY = 0.5f; @@ -724,7 +724,8 @@ void MyAvatar::updateLookAtTargetAvatar() { Avatar* avatar = static_cast(avatarPointer.data()); avatar->setIsLookAtTarget(false); if (!avatar->isMyAvatar()) { - float angleTo = glm::angle(getHead()->getFinalOrientation() * glm::vec3(0.0f, 0.0f, -1.0f), + glm::vec3 DEFAULT_GAZE_IN_HEAD_FRAME = glm::vec3(0.0f, 0.0f, -1.0f); + float angleTo = glm::angle(getHead()->getFinalOrientationInWorldFrame() * DEFAULT_GAZE_IN_HEAD_FRAME, glm::normalize(avatar->getHead()->getEyePosition() - getHead()->getEyePosition())); if (angleTo < smallestAngleTo) { _lookAtTargetAvatar = avatarPointer; diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 8b229590fd..f46f9a6336 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -236,8 +236,8 @@ void SkeletonModel::maybeUpdateLeanRotation(const JointState& parentState, const return; } // get the rotation axes in joint space and use them to adjust the rotation - glm::mat3 axes = glm::mat3_cast(_rotation); - glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getHybridTransform() * glm::translate(state.getDefaultTranslationInParentFrame()) * + glm::mat3 axes = glm::mat3_cast(glm::quat()); + glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getTransformInModelFrame() * glm::translate(state.getDefaultTranslationInParentFrame()) * joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation))); state._rotation = glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanSideways(), glm::normalize(inverse * axes[2])) * glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanForward(), @@ -263,7 +263,7 @@ void SkeletonModel::renderJointConstraints(int jointIndex) { do { const FBXJoint& joint = geometry.joints.at(jointIndex); const JointState& jointState = _jointStates.at(jointIndex); - glm::vec3 position = extractTranslation(jointState.getHybridTransform()) + _translation; + glm::vec3 position = _rotation * jointState.getPositionInModelFrame() + _translation; glPushMatrix(); glTranslatef(position.x, position.y, position.z); From 30d936c15b39abe58ea52e35933abac105f657b0 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 4 Jun 2014 10:52:10 -0700 Subject: [PATCH 12/29] getJointPosition -> getJointPositionInWorldFrame --- interface/src/avatar/Avatar.cpp | 6 +++--- interface/src/avatar/FaceModel.cpp | 4 ++-- interface/src/avatar/SkeletonModel.cpp | 20 ++++++++++---------- interface/src/devices/PrioVR.cpp | 2 +- interface/src/renderer/Model.cpp | 13 ++++++------- interface/src/renderer/Model.h | 2 +- 6 files changed, 23 insertions(+), 24 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 870d5b1a53..baf46605fd 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -377,7 +377,7 @@ void Avatar::simulateAttachments(float deltaTime) { if (!isMyAvatar()) { model->setLODDistance(getLODDistance()); } - if (_skeletonModel.getJointPosition(jointIndex, jointPosition) && + if (_skeletonModel.getJointPositionInWorldFrame(jointIndex, jointPosition) && _skeletonModel.getJointCombinedRotation(jointIndex, jointRotation)) { model->setTranslation(jointPosition + jointRotation * attachment.translation * _scale); model->setRotation(jointRotation * attachment.rotation); @@ -713,7 +713,7 @@ glm::vec3 Avatar::getJointPosition(int index) const { return position; } glm::vec3 position; - _skeletonModel.getJointPosition(index, position); + _skeletonModel.getJointPositionInWorldFrame(index, position); return position; } @@ -725,7 +725,7 @@ glm::vec3 Avatar::getJointPosition(const QString& name) const { return position; } glm::vec3 position; - _skeletonModel.getJointPosition(getJointIndex(name), position); + _skeletonModel.getJointPositionInWorldFrame(getJointIndex(name), position); return position; } diff --git a/interface/src/avatar/FaceModel.cpp b/interface/src/avatar/FaceModel.cpp index 4fb2faf5cf..93cd93b71c 100644 --- a/interface/src/avatar/FaceModel.cpp +++ b/interface/src/avatar/FaceModel.cpp @@ -94,6 +94,6 @@ bool FaceModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEy return false; } const FBXGeometry& geometry = _geometry->getFBXGeometry(); - return getJointPosition(geometry.leftEyeJointIndex, firstEyePosition) && - getJointPosition(geometry.rightEyeJointIndex, secondEyePosition); + return getJointPositionInWorldFrame(geometry.leftEyeJointIndex, firstEyePosition) && + getJointPositionInWorldFrame(geometry.rightEyeJointIndex, secondEyePosition); } diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index f46f9a6336..7004d12ffe 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -373,11 +373,11 @@ void SkeletonModel::setHandPositionInModelFrame(int jointIndex, const glm::vec3& } bool SkeletonModel::getLeftHandPosition(glm::vec3& position) const { - return getJointPosition(getLeftHandJointIndex(), position); + return getJointPositionInWorldFrame(getLeftHandJointIndex(), position); } bool SkeletonModel::getRightHandPosition(glm::vec3& position) const { - return getJointPosition(getRightHandJointIndex(), position); + return getJointPositionInWorldFrame(getRightHandJointIndex(), position); } bool SkeletonModel::restoreLeftHandPosition(float fraction, float priority) { @@ -385,7 +385,7 @@ bool SkeletonModel::restoreLeftHandPosition(float fraction, float priority) { } bool SkeletonModel::getLeftShoulderPosition(glm::vec3& position) const { - return getJointPosition(getLastFreeJointIndex(getLeftHandJointIndex()), position); + return getJointPositionInWorldFrame(getLastFreeJointIndex(getLeftHandJointIndex()), position); } float SkeletonModel::getLeftArmLength() const { @@ -397,7 +397,7 @@ bool SkeletonModel::restoreRightHandPosition(float fraction, float priority) { } bool SkeletonModel::getRightShoulderPosition(glm::vec3& position) const { - return getJointPosition(getLastFreeJointIndex(getRightHandJointIndex()), position); + return getJointPositionInWorldFrame(getLastFreeJointIndex(getRightHandJointIndex()), position); } float SkeletonModel::getRightArmLength() const { @@ -405,11 +405,11 @@ float SkeletonModel::getRightArmLength() const { } bool SkeletonModel::getHeadPosition(glm::vec3& headPosition) const { - return isActive() && getJointPosition(_geometry->getFBXGeometry().headJointIndex, headPosition); + return isActive() && getJointPositionInWorldFrame(_geometry->getFBXGeometry().headJointIndex, headPosition); } bool SkeletonModel::getNeckPosition(glm::vec3& neckPosition) const { - return isActive() && getJointPosition(_geometry->getFBXGeometry().neckJointIndex, neckPosition); + return isActive() && getJointPositionInWorldFrame(_geometry->getFBXGeometry().neckJointIndex, neckPosition); } bool SkeletonModel::getNeckParentRotation(glm::quat& neckParentRotation) const { @@ -428,14 +428,14 @@ bool SkeletonModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& seco return false; } const FBXGeometry& geometry = _geometry->getFBXGeometry(); - if (getJointPosition(geometry.leftEyeJointIndex, firstEyePosition) && - getJointPosition(geometry.rightEyeJointIndex, secondEyePosition)) { + if (getJointPositionInWorldFrame(geometry.leftEyeJointIndex, firstEyePosition) && + getJointPositionInWorldFrame(geometry.rightEyeJointIndex, secondEyePosition)) { return true; } // no eye joints; try to estimate based on head/neck joints glm::vec3 neckPosition, headPosition; - if (getJointPosition(geometry.neckJointIndex, neckPosition) && - getJointPosition(geometry.headJointIndex, headPosition)) { + if (getJointPositionInWorldFrame(geometry.neckJointIndex, neckPosition) && + getJointPositionInWorldFrame(geometry.headJointIndex, headPosition)) { const float EYE_PROPORTION = 0.6f; glm::vec3 baseEyePosition = glm::mix(neckPosition, headPosition, EYE_PROPORTION); glm::quat headRotation; diff --git a/interface/src/devices/PrioVR.cpp b/interface/src/devices/PrioVR.cpp index ab29fc004b..65cdb962e1 100644 --- a/interface/src/devices/PrioVR.cpp +++ b/interface/src/devices/PrioVR.cpp @@ -92,7 +92,7 @@ static void setPalm(float deltaTime, int index) { skeletonModel->getJointRotation(jointIndex, rotation, true); rotation = inverseRotation * rotation * glm::quat(glm::vec3(0.0f, -PI_OVER_TWO, 0.0f)); } - skeletonModel->getJointPosition(jointIndex, position); + skeletonModel->getJointPositionInWorldFrame(jointIndex, position); position = inverseRotation * (position - skeletonModel->getTranslation()); palm->setRawRotation(rotation); diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index a345a32707..f603dea55a 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -747,12 +747,11 @@ void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bo } } -bool Model::getJointPosition(int jointIndex, glm::vec3& position) const { +bool Model::getJointPositionInWorldFrame(int jointIndex, glm::vec3& position) const { if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return false; } - position = _translation + extractTranslation(_jointStates[jointIndex].getHybridTransform()); - //position = _translation + _rotation * _jointState[jointIndex].getPositionInModelFrame(); + position = _translation + _rotation * _jointStates[jointIndex].getPositionInModelFrame(); return true; } @@ -1234,7 +1233,7 @@ void Model::simulateInternal(float deltaTime) { glm::vec3 jointTranslation = _translation; glm::quat jointRotation = _rotation; - getJointPosition(attachment.jointIndex, jointTranslation); + getJointPositionInWorldFrame(attachment.jointIndex, jointTranslation); getJointRotationInWorldFrame(attachment.jointIndex, jointRotation); model->setTranslation(jointTranslation + jointRotation * attachment.translation * _scale); @@ -1508,12 +1507,12 @@ void Model::applyCollision(CollisionInfo& collision) { glm::vec3 jointPosition(0.0f); int jointIndex = collision._intData; - if (getJointPosition(jointIndex, jointPosition)) { + if (getJointPositionInWorldFrame(jointIndex, jointPosition)) { const FBXJoint& joint = _geometry->getFBXGeometry().joints[jointIndex]; if (joint.parentIndex != -1) { // compute the approximate distance (travel) that the joint needs to move glm::vec3 start; - getJointPosition(joint.parentIndex, start); + getJointPositionInWorldFrame(joint.parentIndex, start); glm::vec3 contactPoint = collision._contactPoint - start; glm::vec3 penetrationEnd = contactPoint + collision._penetration; glm::vec3 axis = glm::cross(contactPoint, penetrationEnd); @@ -1524,7 +1523,7 @@ void Model::applyCollision(CollisionInfo& collision) { float angle = asinf(travel / (glm::length(contactPoint) * glm::length(penetrationEnd))); axis = glm::normalize(axis); glm::vec3 end; - getJointPosition(jointIndex, end); + getJointPositionInWorldFrame(jointIndex, end); // transform into model-frame glm::vec3 newEnd = glm::inverse(_rotation) * (start + glm::angleAxis(angle, axis) * (end - start) - _translation); // try to move it diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index eb5b4cd7c8..e4c25c8937 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -173,7 +173,7 @@ public: /// Returns the index of the last free ancestor of the indexed joint, or -1 if not found. int getLastFreeJointIndex(int jointIndex) const; - bool getJointPosition(int jointIndex, glm::vec3& position) const; + bool getJointPositionInWorldFrame(int jointIndex, glm::vec3& position) const; bool getJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const; bool getJointCombinedRotation(int jointIndex, glm::quat& rotation) const; From 729c01ddbfacfd0b02be57adfcb5ed36e9c90d4c Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 4 Jun 2014 11:25:38 -0700 Subject: [PATCH 13/29] remove more getHybridTransform() calls --- interface/src/renderer/Model.cpp | 24 ++++++++++-------------- interface/src/renderer/Model.h | 2 -- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index f603dea55a..52037acb2f 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -987,16 +987,16 @@ void Model::updateShapePositions() { glm::vec3 rootPosition(0.0f); _boundingRadius = 0.0f; float uniformScale = extractUniformScale(_scale); - const FBXGeometry& geometry = _geometry->getFBXGeometry(); for (int i = 0; i < _jointStates.size(); i++) { - const FBXJoint& joint = geometry.joints[i]; + const JointState& state = _jointStates[i]; + const FBXJoint& joint = state.getFBXJoint(); // shape position and rotation need to be in world-frame - glm::quat rotationInWorldFrame = _rotation * _jointStates[i].getRotationInModelFrame(); - glm::vec3 jointToShapeOffset = uniformScale * (rotationInWorldFrame * joint.shapePosition); - glm::vec3 worldPosition = extractTranslation(_jointStates[i].getHybridTransform()) + jointToShapeOffset + _translation; + glm::quat stateRotation = state.getRotationInModelFrame(); + glm::vec3 shapeOffset = uniformScale * (stateRotation * joint.shapePosition); + glm::vec3 worldPosition = _translation + _rotation * (state.getPositionInModelFrame() + shapeOffset); Shape* shape = _jointShapes[i]; shape->setPosition(worldPosition); - shape->setRotation(rotationInWorldFrame * joint.shapeRotation); + shape->setRotation(_rotation * stateRotation * joint.shapeRotation); float distance = glm::distance(worldPosition, _translation) + shape->getBoundingRadius(); if (distance > _boundingRadius) { _boundingRadius = distance; @@ -1018,12 +1018,12 @@ bool Model::findRayIntersection(const glm::vec3& origin, const glm::vec3& direct float radiusScale = extractUniformScale(_scale); for (int i = 0; i < _jointStates.size(); i++) { const FBXJoint& joint = geometry.joints[i]; - glm::vec3 end = extractTranslation(_jointStates[i].getHybridTransform()); + glm::vec3 end = _jointStates[i].getPositionInWorldFrame(_rotation, _translation); float endRadius = joint.boneRadius * radiusScale; glm::vec3 start = end; float startRadius = joint.boneRadius * radiusScale; if (joint.parentIndex != -1) { - start = extractTranslation(_jointStates[joint.parentIndex].getHybridTransform()); + start = _jointStates[joint.parentIndex].getPositionInWorldFrame(_rotation, _translation); startRadius = geometry.joints[joint.parentIndex].boneRadius * radiusScale; } // for now, use average of start and end radii @@ -1245,12 +1245,13 @@ void Model::simulateInternal(float deltaTime) { } } + glm::mat4 modelToWorld = glm::mat4_cast(_rotation); for (int i = 0; i < _meshStates.size(); i++) { MeshState& state = _meshStates[i]; const FBXMesh& mesh = geometry.meshes.at(i); for (int j = 0; j < mesh.clusters.size(); j++) { const FBXCluster& cluster = mesh.clusters.at(j); - state.clusterMatrices[j] = _jointStates[cluster.jointIndex].getHybridTransform() * cluster.inverseBindMatrix; + state.clusterMatrices[j] = modelToWorld * _jointStates[cluster.jointIndex].getTransformInModelFrame() * cluster.inverseBindMatrix; } } @@ -2018,11 +2019,6 @@ void AnimationHandle::replaceMatchingPriorities(float newPriority) { } } -glm::mat4 Model::getBaseTransform(const glm::mat4& geometryOffset) const { - //return glm::translate(_translation) * glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset) * geometryOffset; - return glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset) * geometryOffset; -} - // ---------------------------------------------------------------------------- // JointState TODO: move this class to its own files // ---------------------------------------------------------------------------- diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index e4c25c8937..9004003d77 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -221,8 +221,6 @@ public: const CapsuleShape& getBoundingShape() const { return _boundingShape; } - glm::mat4 getBaseTransform(const glm::mat4& geometryOffset) const; - protected: QSharedPointer _geometry; From 5d8e3d447aadcd2dd041dd9feb12d722a511e23b Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 4 Jun 2014 11:36:00 -0700 Subject: [PATCH 14/29] remove JointState::getRota/PositionInWorldFrame() instead: use getRotat/PositionInModelFrame() and do math --- interface/src/renderer/Model.cpp | 14 +++----------- interface/src/renderer/Model.h | 3 --- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 52037acb2f..daf87486ac 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -775,7 +775,7 @@ bool Model::getJointCombinedRotation(int jointIndex, glm::quat& rotation) const if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return false; } - rotation = _jointStates[jointIndex].getRotationInWorldFrame(_rotation); + rotation = _rotation * _jointStates[jointIndex].getRotationInModelFrame(); return true; } @@ -1018,12 +1018,12 @@ bool Model::findRayIntersection(const glm::vec3& origin, const glm::vec3& direct float radiusScale = extractUniformScale(_scale); for (int i = 0; i < _jointStates.size(); i++) { const FBXJoint& joint = geometry.joints[i]; - glm::vec3 end = _jointStates[i].getPositionInWorldFrame(_rotation, _translation); + glm::vec3 end = _translation + _rotation * _jointStates[i].getPositionInModelFrame(); float endRadius = joint.boneRadius * radiusScale; glm::vec3 start = end; float startRadius = joint.boneRadius * radiusScale; if (joint.parentIndex != -1) { - start = _jointStates[joint.parentIndex].getPositionInWorldFrame(_rotation, _translation); + start = _translation + _rotation * _jointStates[joint.parentIndex].getPositionInModelFrame(); startRadius = geometry.joints[joint.parentIndex].boneRadius * radiusScale; } // for now, use average of start and end radii @@ -2053,14 +2053,6 @@ void JointState::computeTransformInModelFrame(const glm::mat4& parentTransform) _rotationInModelFrame = extractRotation(_transformInModelFrame); } -glm::quat JointState::getRotationInWorldFrame(const glm::quat& baseRotation) const { - return baseRotation * _rotationInModelFrame; -} - -glm::vec3 JointState::getPositionInWorldFrame(const glm::quat& baseRotation, const glm::vec3& basePosition) const { - return basePosition + baseRotation * extractTranslation(_transformInModelFrame); -} - void JointState::computeTransforms(const glm::mat4& parentTransform, const glm::quat& baseRotation) { assert(_fbxJoint != NULL); diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 9004003d77..649f5ac069 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -46,9 +46,6 @@ public: glm::quat getRotationInModelFrame() const { return _rotationInModelFrame; } glm::vec3 getPositionInModelFrame() const { return extractTranslation(_transformInModelFrame); } - glm::quat getRotationInWorldFrame(const glm::quat& baseRotation) const; - glm::vec3 getPositionInWorldFrame(const glm::quat& baseRotation, const glm::vec3& basePosition) const; - /// computes new _transform and _combinedRotation void computeTransforms(const glm::mat4& baseTransform, const glm::quat& baseRotation); From 19f0f453a5376253d62aa2200ef9df0069f142c6 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 4 Jun 2014 11:52:07 -0700 Subject: [PATCH 15/29] remove JointState::setRotation() instead use JointState::setRotationInModelFrame() --- interface/src/avatar/SkeletonModel.cpp | 2 +- interface/src/renderer/Model.cpp | 8 -------- interface/src/renderer/Model.h | 4 +--- 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 7004d12ffe..93374ef3d0 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -46,7 +46,7 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { int jointIndex = geometry.humanIKJointIndices.at(humanIKJointIndex); if (jointIndex != -1) { JointState& state = _jointStates[jointIndex]; - state.setRotation(_rotation * prioVR->getJointRotations().at(i), PALM_PRIORITY); + state.setRotationInModelFrame(prioVR->getJointRotations().at(i), PALM_PRIORITY); } } return; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index daf87486ac..d32293b9c5 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -2074,14 +2074,6 @@ void JointState::restoreRotation(float fraction, float priority) { } } -void JointState::setRotation(const glm::quat& rotation, float priority) { - assert(_fbxJoint != NULL); - if (priority >= _animationPriority) { - _rotation = _rotation * glm::inverse(_combinedRotation) * rotation * glm::inverse(_fbxJoint->inverseBindRotation); - _animationPriority = priority; - } -} - void JointState::setRotationInModelFrame(const glm::quat& rotation, float priority) { assert(_fbxJoint != NULL); if (priority >= _animationPriority) { diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 649f5ac069..8619cf9c22 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -58,14 +58,12 @@ public: void restoreRotation(float fraction, float priority); - /// \param rotation is from bind- to world-frame + /// \param rotation is from bind-frame to model-frame /// computes parent relative _rotation and sets that /// \warning no combined transforms are updated! - void setRotation(const glm::quat& rotation, float priority); void setRotationInModelFrame(const glm::quat& rotation, float priority); const glm::mat4& getHybridTransform() const { return _transform; } - //const glm::quat& getRotationInWorldFrame() const { return _combinedRotation; } void clearTransformTranslation(); glm::quat _rotation; // rotation relative to parent From d46a90d7638f1533d13166e176e3a9b8f38dda9e Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 4 Jun 2014 11:56:20 -0700 Subject: [PATCH 16/29] remove JointState::_combinedRotation instead use JointState::_rotationInModelFrame --- interface/src/renderer/Model.cpp | 14 +++++--------- interface/src/renderer/Model.h | 5 ++--- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index d32293b9c5..3f2ac8c197 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -201,13 +201,12 @@ QVector Model::createJointStates(const FBXGeometry& geometry) { if (parentIndex == -1) { _rootIndex = i; glm::mat4 baseTransform = glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset) * geometry.offset; - state.computeTransforms(baseTransform, _rotation); + state.computeTransforms(baseTransform); ++numJointsSet; jointIsSet[i] = true; } else if (jointIsSet[parentIndex]) { const JointState& parentState = jointStates.at(parentIndex); - glm::quat parentRotation = _rotation * parentState.getRotationInModelFrame(); - state.computeTransforms(parentState.getHybridTransform(), parentRotation); + state.computeTransforms(parentState.getHybridTransform()); ++numJointsSet; jointIsSet[i] = true; } @@ -1280,11 +1279,10 @@ void Model::updateJointState(int index) { if (parentIndex == -1) { const FBXGeometry& geometry = _geometry->getFBXGeometry(); glm::mat4 baseTransform = glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset) * geometry.offset; - state.computeTransforms(baseTransform, _rotation); + state.computeTransforms(baseTransform); } else { const JointState& parentState = _jointStates.at(parentIndex); - glm::quat parentRotation = _rotation * parentState.getRotationInModelFrame(); - state.computeTransforms(parentState.getHybridTransform(), parentRotation); + state.computeTransforms(parentState.getHybridTransform()); } } @@ -2039,7 +2037,6 @@ void JointState::copyState(const JointState& state) { _transformInModelFrame = state._transformInModelFrame; _rotationInModelFrame = extractRotation(_transformInModelFrame); - _combinedRotation = state._combinedRotation; _transform = state._transform; _animationPriority = state._animationPriority; @@ -2053,13 +2050,12 @@ void JointState::computeTransformInModelFrame(const glm::mat4& parentTransform) _rotationInModelFrame = extractRotation(_transformInModelFrame); } -void JointState::computeTransforms(const glm::mat4& parentTransform, const glm::quat& baseRotation) { +void JointState::computeTransforms(const glm::mat4& parentTransform) { assert(_fbxJoint != NULL); glm::quat modifiedRotation = _fbxJoint->preRotation * _rotation * _fbxJoint->postRotation; glm::mat4 modifiedTransform = _fbxJoint->preTransform * glm::mat4_cast(modifiedRotation) * _fbxJoint->postTransform; _transform = parentTransform * glm::translate(_fbxJoint->translation) * modifiedTransform; - _combinedRotation = baseRotation * modifiedRotation; } glm::quat JointState::getRotationFromBindToModelFrame() const { diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 8619cf9c22..e7fa2917ad 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -46,8 +46,8 @@ public: glm::quat getRotationInModelFrame() const { return _rotationInModelFrame; } glm::vec3 getPositionInModelFrame() const { return extractTranslation(_transformInModelFrame); } - /// computes new _transform and _combinedRotation - void computeTransforms(const glm::mat4& baseTransform, const glm::quat& baseRotation); + /// computes new _transform + void computeTransforms(const glm::mat4& baseTransform); /// \return rotation from bind to model frame glm::quat getRotationFromBindToModelFrame() const; @@ -72,7 +72,6 @@ public: private: glm::mat4 _transformInModelFrame; glm::quat _rotationInModelFrame; - glm::quat _combinedRotation; // rotation from joint local to world frame glm::mat4 _transform; // rotation to world frame + translation in model frame const FBXJoint* _fbxJoint; // JointState does NOT own its FBXJoint From b1b7f6bdc48872b3ac611132ec247f6a36c1a4b7 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 4 Jun 2014 12:03:01 -0700 Subject: [PATCH 17/29] remove last world-frame transfoms from JointState --- interface/src/renderer/Model.cpp | 56 -------------------------------- interface/src/renderer/Model.h | 5 --- 2 files changed, 61 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 3f2ac8c197..df6381d447 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -181,38 +181,6 @@ QVector Model::createJointStates(const FBXGeometry& geometry) { state.computeTransformInModelFrame(parentState.getTransformInModelFrame()); } } - - // compute transforms - // Unfortunately, the joints are not neccessarily in order from parents to children, - // so we must iterate over the list multiple times until all are set correctly. - QVector jointIsSet; - jointIsSet.fill(false, numJoints); - int numJointsSet = 0; - int lastNumJointsSet = -1; - while (numJointsSet < numJoints && numJointsSet != lastNumJointsSet) { - lastNumJointsSet = numJointsSet; - for (int i = 0; i < numJoints; ++i) { - if (jointIsSet[i]) { - continue; - } - JointState& state = jointStates[i]; - const FBXJoint& joint = state.getFBXJoint(); - int parentIndex = joint.parentIndex; - if (parentIndex == -1) { - _rootIndex = i; - glm::mat4 baseTransform = glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset) * geometry.offset; - state.computeTransforms(baseTransform); - ++numJointsSet; - jointIsSet[i] = true; - } else if (jointIsSet[parentIndex]) { - const JointState& parentState = jointStates.at(parentIndex); - state.computeTransforms(parentState.getHybridTransform()); - ++numJointsSet; - jointIsSet[i] = true; - } - } - } - return jointStates; } @@ -1274,16 +1242,6 @@ void Model::updateJointState(int index) { const JointState& parentState = _jointStates.at(parentIndex); state.computeTransformInModelFrame(parentState.getTransformInModelFrame()); } - - // compute hybrid transforms - if (parentIndex == -1) { - const FBXGeometry& geometry = _geometry->getFBXGeometry(); - glm::mat4 baseTransform = glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset) * geometry.offset; - state.computeTransforms(baseTransform); - } else { - const JointState& parentState = _jointStates.at(parentIndex); - state.computeTransforms(parentState.getHybridTransform()); - } } bool Model::setJointPositionInModelFrame(int jointIndex, const glm::vec3& position, const glm::quat& rotation, bool useRotation, @@ -2034,11 +1992,8 @@ void JointState::setFBXJoint(const FBXJoint* joint) { void JointState::copyState(const JointState& state) { _rotation = state._rotation; - _transformInModelFrame = state._transformInModelFrame; _rotationInModelFrame = extractRotation(_transformInModelFrame); - _transform = state._transform; - _animationPriority = state._animationPriority; // DO NOT copy _fbxJoint } @@ -2050,14 +2005,6 @@ void JointState::computeTransformInModelFrame(const glm::mat4& parentTransform) _rotationInModelFrame = extractRotation(_transformInModelFrame); } -void JointState::computeTransforms(const glm::mat4& parentTransform) { - assert(_fbxJoint != NULL); - - glm::quat modifiedRotation = _fbxJoint->preRotation * _rotation * _fbxJoint->postRotation; - glm::mat4 modifiedTransform = _fbxJoint->preTransform * glm::mat4_cast(modifiedRotation) * _fbxJoint->postTransform; - _transform = parentTransform * glm::translate(_fbxJoint->translation) * modifiedTransform; -} - glm::quat JointState::getRotationFromBindToModelFrame() const { return _rotationInModelFrame * _fbxJoint->inverseBindRotation; } @@ -2079,9 +2026,6 @@ void JointState::setRotationInModelFrame(const glm::quat& rotation, float priori } void JointState::clearTransformTranslation() { - _transform[3][0] = 0.0f; - _transform[3][1] = 0.0f; - _transform[3][2] = 0.0f; _transformInModelFrame[3][0] = 0.0f; _transformInModelFrame[3][1] = 0.0f; _transformInModelFrame[3][2] = 0.0f; diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index e7fa2917ad..9aeb6f68ba 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -46,9 +46,6 @@ public: glm::quat getRotationInModelFrame() const { return _rotationInModelFrame; } glm::vec3 getPositionInModelFrame() const { return extractTranslation(_transformInModelFrame); } - /// computes new _transform - void computeTransforms(const glm::mat4& baseTransform); - /// \return rotation from bind to model frame glm::quat getRotationFromBindToModelFrame() const; @@ -63,7 +60,6 @@ public: /// \warning no combined transforms are updated! void setRotationInModelFrame(const glm::quat& rotation, float priority); - const glm::mat4& getHybridTransform() const { return _transform; } void clearTransformTranslation(); glm::quat _rotation; // rotation relative to parent @@ -72,7 +68,6 @@ public: private: glm::mat4 _transformInModelFrame; glm::quat _rotationInModelFrame; - glm::mat4 _transform; // rotation to world frame + translation in model frame const FBXJoint* _fbxJoint; // JointState does NOT own its FBXJoint }; From d32e14ca048e6667eef08d0b5c5fdad794b9596f Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 4 Jun 2014 13:27:28 -0700 Subject: [PATCH 18/29] renames of JointState data members --- interface/src/avatar/FaceModel.cpp | 4 +-- interface/src/avatar/SkeletonModel.cpp | 4 +-- interface/src/renderer/Model.cpp | 48 +++++++++++++------------- interface/src/renderer/Model.h | 18 +++++----- 4 files changed, 37 insertions(+), 37 deletions(-) diff --git a/interface/src/avatar/FaceModel.cpp b/interface/src/avatar/FaceModel.cpp index 93cd93b71c..652ecdec32 100644 --- a/interface/src/avatar/FaceModel.cpp +++ b/interface/src/avatar/FaceModel.cpp @@ -51,7 +51,7 @@ void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBX glm::mat3 axes = glm::mat3_cast(glm::quat()); glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getTransformInModelFrame() * glm::translate(state.getDefaultTranslationInParentFrame()) * joint.preTransform * glm::mat4_cast(joint.preRotation))); - state._rotation = glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalRoll(), glm::normalize(inverse * axes[2])) + state._rotationInParentFrame = glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalRoll(), glm::normalize(inverse * axes[2])) * glm::angleAxis(RADIANS_PER_DEGREE * _owningHead->getFinalYaw(), glm::normalize(inverse * axes[1])) * glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalPitch(), glm::normalize(inverse * axes[0])) * joint.rotation; @@ -68,7 +68,7 @@ void FaceModel::maybeUpdateEyeRotation(const JointState& parentState, const FBXJ _owningHead->getSaccade() - _translation, 1.0f)); glm::quat between = rotationBetween(front, lookAt); const float MAX_ANGLE = 30.0f * RADIANS_PER_DEGREE; - state._rotation = glm::angleAxis(glm::clamp(glm::angle(between), -MAX_ANGLE, MAX_ANGLE), glm::axis(between)) * + state._rotationInParentFrame = glm::angleAxis(glm::clamp(glm::angle(between), -MAX_ANGLE, MAX_ANGLE), glm::axis(between)) * joint.rotation; } diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 93374ef3d0..cf9b96cbd1 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -200,7 +200,7 @@ void SkeletonModel::applyPalmDataInModelFrame(int jointIndex, PalmData& palm) { JointState& parentState = _jointStates[parentJointIndex]; parentState.setRotationInModelFrame(palmRotation, PALM_PRIORITY); // lock hand to forearm by slamming its rotation (in parent-frame) to identity - _jointStates[jointIndex]._rotation = glm::quat(); + _jointStates[jointIndex]._rotationInParentFrame = glm::quat(); } else { setJointPositionInModelFrame(jointIndex, palmPosition, palmRotation, true, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY); @@ -239,7 +239,7 @@ void SkeletonModel::maybeUpdateLeanRotation(const JointState& parentState, const glm::mat3 axes = glm::mat3_cast(glm::quat()); glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getTransformInModelFrame() * glm::translate(state.getDefaultTranslationInParentFrame()) * joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation))); - state._rotation = glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanSideways(), + state._rotationInParentFrame = glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanSideways(), glm::normalize(inverse * axes[2])) * glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanForward(), glm::normalize(inverse * axes[0])) * joint.rotation; } diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index df6381d447..d1a8587a5c 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -459,7 +459,7 @@ void Model::reset() { } const FBXGeometry& geometry = _geometry->getFBXGeometry(); for (int i = 0; i < _jointStates.size(); i++) { - _jointStates[i]._rotation = geometry.joints.at(i).rotation; + _jointStates[i]._rotationInParentFrame = geometry.joints.at(i).rotation; } } @@ -669,7 +669,7 @@ bool Model::getJointState(int index, glm::quat& rotation) const { if (index == -1 || index >= _jointStates.size()) { return false; } - rotation = _jointStates.at(index)._rotation; + rotation = _jointStates.at(index)._rotationInParentFrame; const glm::quat& defaultRotation = _geometry->getFBXGeometry().joints.at(index).rotation; return glm::abs(rotation.x - defaultRotation.x) >= EPSILON || glm::abs(rotation.y - defaultRotation.y) >= EPSILON || @@ -682,7 +682,7 @@ void Model::setJointState(int index, bool valid, const glm::quat& rotation, floa JointState& state = _jointStates[index]; if (priority >= state._animationPriority) { if (valid) { - state._rotation = rotation; + state._rotationInParentFrame = rotation; state._animationPriority = priority; } else { state.restoreRotation(1.0f, priority); @@ -1932,7 +1932,7 @@ void AnimationHandle::simulate(float deltaTime) { if (mapping != -1) { JointState& state = _model->_jointStates[mapping]; if (_priority >= state._animationPriority) { - state._rotation = frame.rotations.at(i); + state._rotationInParentFrame = frame.rotations.at(i); state._animationPriority = _priority; } } @@ -1956,7 +1956,7 @@ void AnimationHandle::simulate(float deltaTime) { if (mapping != -1) { JointState& state = _model->_jointStates[mapping]; if (_priority >= state._animationPriority) { - state._rotation = safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction); + state._rotationInParentFrame = safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction); state._animationPriority = _priority; } } @@ -1985,34 +1985,34 @@ JointState::JointState() : void JointState::setFBXJoint(const FBXJoint* joint) { assert(joint != NULL); - _rotation = joint->rotation; + _rotationInParentFrame = joint->rotation; // NOTE: JointState does not own the FBXJoint to which it points. _fbxJoint = joint; } void JointState::copyState(const JointState& state) { - _rotation = state._rotation; - _transformInModelFrame = state._transformInModelFrame; - _rotationInModelFrame = extractRotation(_transformInModelFrame); + _rotationInParentFrame = state._rotationInParentFrame; + _transform = state._transform; + _rotation = extractRotation(_transform); _animationPriority = state._animationPriority; // DO NOT copy _fbxJoint } void JointState::computeTransformInModelFrame(const glm::mat4& parentTransform) { - glm::quat modifiedRotation = _fbxJoint->preRotation * _rotation * _fbxJoint->postRotation; + glm::quat modifiedRotation = _fbxJoint->preRotation * _rotationInParentFrame * _fbxJoint->postRotation; glm::mat4 modifiedTransform = _fbxJoint->preTransform * glm::mat4_cast(modifiedRotation) * _fbxJoint->postTransform; - _transformInModelFrame = parentTransform * glm::translate(_fbxJoint->translation) * modifiedTransform; - _rotationInModelFrame = extractRotation(_transformInModelFrame); + _transform = parentTransform * glm::translate(_fbxJoint->translation) * modifiedTransform; + _rotation = extractRotation(_transform); } glm::quat JointState::getRotationFromBindToModelFrame() const { - return _rotationInModelFrame * _fbxJoint->inverseBindRotation; + return _rotation * _fbxJoint->inverseBindRotation; } void JointState::restoreRotation(float fraction, float priority) { assert(_fbxJoint != NULL); if (priority == _animationPriority) { - _rotation = safeMix(_rotation, _fbxJoint->rotation, fraction); + _rotationInParentFrame = safeMix(_rotationInParentFrame, _fbxJoint->rotation, fraction); _animationPriority = 0.0f; } } @@ -2020,15 +2020,15 @@ void JointState::restoreRotation(float fraction, float priority) { void JointState::setRotationInModelFrame(const glm::quat& rotation, float priority) { assert(_fbxJoint != NULL); if (priority >= _animationPriority) { - _rotation = _rotation * glm::inverse(_rotationInModelFrame) * rotation * glm::inverse(_fbxJoint->inverseBindRotation); + _rotationInParentFrame = _rotationInParentFrame * glm::inverse(_rotation) * rotation * glm::inverse(_fbxJoint->inverseBindRotation); _animationPriority = priority; } } void JointState::clearTransformTranslation() { - _transformInModelFrame[3][0] = 0.0f; - _transformInModelFrame[3][1] = 0.0f; - _transformInModelFrame[3][2] = 0.0f; + _transform[3][0] = 0.0f; + _transform[3][1] = 0.0f; + _transform[3][2] = 0.0f; } void JointState::applyRotationDeltaInModelFrame(const glm::quat& delta, bool constrain, float priority) { @@ -2040,15 +2040,15 @@ void JointState::applyRotationDeltaInModelFrame(const glm::quat& delta, bool con if (!constrain || (_fbxJoint->rotationMin == glm::vec3(-PI, -PI, -PI) && _fbxJoint->rotationMax == glm::vec3(PI, PI, PI))) { // no constraints - _rotation = _rotation * glm::inverse(_rotationInModelFrame) * delta * _rotationInModelFrame; - _rotationInModelFrame = delta * _rotationInModelFrame; + _rotationInParentFrame = _rotationInParentFrame * glm::inverse(_rotation) * delta * _rotation; + _rotation = delta * _rotation; return; } - glm::quat targetRotation = delta * _rotationInModelFrame; - glm::vec3 eulers = safeEulerAngles(_rotation * glm::inverse(_rotationInModelFrame) * targetRotation); + glm::quat targetRotation = delta * _rotation; + glm::vec3 eulers = safeEulerAngles(_rotationInParentFrame * glm::inverse(_rotation) * targetRotation); glm::quat newRotation = glm::quat(glm::clamp(eulers, _fbxJoint->rotationMin, _fbxJoint->rotationMax)); - _rotationInModelFrame = _rotationInModelFrame * glm::inverse(_rotation) * newRotation; - _rotation = newRotation; + _rotation = _rotation * glm::inverse(_rotationInParentFrame) * newRotation; + _rotationInParentFrame = newRotation; } const glm::vec3& JointState::getDefaultTranslationInParentFrame() const { diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 9aeb6f68ba..955207445b 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -41,10 +41,10 @@ public: void copyState(const JointState& state); void computeTransformInModelFrame(const glm::mat4& parentTransform); - const glm::mat4& getTransformInModelFrame() const { return _transformInModelFrame; } + const glm::mat4& getTransformInModelFrame() const { return _transform; } - glm::quat getRotationInModelFrame() const { return _rotationInModelFrame; } - glm::vec3 getPositionInModelFrame() const { return extractTranslation(_transformInModelFrame); } + glm::quat getRotationInModelFrame() const { return _rotation; } + glm::vec3 getPositionInModelFrame() const { return extractTranslation(_transform); } /// \return rotation from bind to model frame glm::quat getRotationFromBindToModelFrame() const; @@ -55,19 +55,19 @@ public: void restoreRotation(float fraction, float priority); - /// \param rotation is from bind-frame to model-frame - /// computes parent relative _rotation and sets that - /// \warning no combined transforms are updated! + /// \param rotation is from bind- to model-frame + /// computes and sets new _rotationInParentFrame + /// NOTE: the JointState's model-frame transform/rotation are NOT updated! void setRotationInModelFrame(const glm::quat& rotation, float priority); void clearTransformTranslation(); - glm::quat _rotation; // rotation relative to parent + glm::quat _rotationInParentFrame; // joint- to parentJoint-frame float _animationPriority; // the priority of the animation affecting this joint private: - glm::mat4 _transformInModelFrame; - glm::quat _rotationInModelFrame; + glm::mat4 _transform; // joint- to model-frame + glm::quat _rotation; // joint- to model-frame const FBXJoint* _fbxJoint; // JointState does NOT own its FBXJoint }; From 4ae58153e0e8a4a2c87ea1f883650c7974ed6191 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 4 Jun 2014 13:31:31 -0700 Subject: [PATCH 19/29] computeTransformInModelFrame -> computeTransform --- interface/src/avatar/FaceModel.cpp | 4 ++-- interface/src/avatar/SkeletonModel.cpp | 2 +- interface/src/renderer/Model.cpp | 20 ++++++++++---------- interface/src/renderer/Model.h | 4 ++-- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/interface/src/avatar/FaceModel.cpp b/interface/src/avatar/FaceModel.cpp index 652ecdec32..601dad5563 100644 --- a/interface/src/avatar/FaceModel.cpp +++ b/interface/src/avatar/FaceModel.cpp @@ -49,7 +49,7 @@ void FaceModel::simulate(float deltaTime, bool fullUpdate) { void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) { // get the rotation axes in joint space and use them to adjust the rotation glm::mat3 axes = glm::mat3_cast(glm::quat()); - glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getTransformInModelFrame() * glm::translate(state.getDefaultTranslationInParentFrame()) * + glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getTransform() * glm::translate(state.getDefaultTranslationInParentFrame()) * joint.preTransform * glm::mat4_cast(joint.preRotation))); state._rotationInParentFrame = glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalRoll(), glm::normalize(inverse * axes[2])) * glm::angleAxis(RADIANS_PER_DEGREE * _owningHead->getFinalYaw(), glm::normalize(inverse * axes[1])) @@ -60,7 +60,7 @@ void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBX void FaceModel::maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) { // likewise with the eye joints // NOTE: at the moment we do the math in the world-frame, hence the inverse transform is more complex than usual. - glm::mat4 inverse = glm::inverse(glm::mat4_cast(_rotation) * parentState.getTransformInModelFrame() * + glm::mat4 inverse = glm::inverse(glm::mat4_cast(_rotation) * parentState.getTransform() * glm::translate(state.getDefaultTranslationInParentFrame()) * joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation)); glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getFinalOrientationInWorldFrame() * IDENTITY_FRONT, 0.0f)); diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index cf9b96cbd1..e689deb0a8 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -237,7 +237,7 @@ void SkeletonModel::maybeUpdateLeanRotation(const JointState& parentState, const } // get the rotation axes in joint space and use them to adjust the rotation glm::mat3 axes = glm::mat3_cast(glm::quat()); - glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getTransformInModelFrame() * glm::translate(state.getDefaultTranslationInParentFrame()) * + glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getTransform() * glm::translate(state.getDefaultTranslationInParentFrame()) * joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation))); state._rotationInParentFrame = glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanSideways(), glm::normalize(inverse * axes[2])) * glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanForward(), diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index d1a8587a5c..8206129c5b 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -175,10 +175,10 @@ QVector Model::createJointStates(const FBXGeometry& geometry) { if (parentIndex == -1) { _rootIndex = i; glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset; - state.computeTransformInModelFrame(parentTransform); + state.computeTransform(parentTransform); } else { const JointState& parentState = jointStates.at(parentIndex); - state.computeTransformInModelFrame(parentState.getTransformInModelFrame()); + state.computeTransform(parentState.getTransform()); } } return jointStates; @@ -726,7 +726,7 @@ bool Model::getJointPositionInModelFrame(int jointIndex, glm::vec3& position) co if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return false; } - position = extractTranslation(_jointStates[jointIndex].getTransformInModelFrame()); + position = extractTranslation(_jointStates[jointIndex].getTransform()); return true; } @@ -1218,7 +1218,7 @@ void Model::simulateInternal(float deltaTime) { const FBXMesh& mesh = geometry.meshes.at(i); for (int j = 0; j < mesh.clusters.size(); j++) { const FBXCluster& cluster = mesh.clusters.at(j); - state.clusterMatrices[j] = modelToWorld * _jointStates[cluster.jointIndex].getTransformInModelFrame() * cluster.inverseBindMatrix; + state.clusterMatrices[j] = modelToWorld * _jointStates[cluster.jointIndex].getTransform() * cluster.inverseBindMatrix; } } @@ -1237,10 +1237,10 @@ void Model::updateJointState(int index) { if (parentIndex == -1) { const FBXGeometry& geometry = _geometry->getFBXGeometry(); glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset; - state.computeTransformInModelFrame(parentTransform); + state.computeTransform(parentTransform); } else { const JointState& parentState = _jointStates.at(parentIndex); - state.computeTransformInModelFrame(parentState.getTransformInModelFrame()); + state.computeTransform(parentState.getTransform()); } } @@ -1275,7 +1275,7 @@ bool Model::setJointPositionInModelFrame(int jointIndex, const glm::vec3& positi } // then, we go from the joint upwards, rotating the end as close as possible to the target - glm::vec3 endPosition = extractTranslation(_jointStates[jointIndex].getTransformInModelFrame()); + glm::vec3 endPosition = extractTranslation(_jointStates[jointIndex].getTransform()); for (int j = 1; freeLineage.at(j - 1) != lastFreeIndex; j++) { int index = freeLineage.at(j); JointState& state = _jointStates[index]; @@ -1283,7 +1283,7 @@ bool Model::setJointPositionInModelFrame(int jointIndex, const glm::vec3& positi if (!(joint.isFree || allIntermediatesFree)) { continue; } - glm::vec3 jointPosition = extractTranslation(state.getTransformInModelFrame()); + glm::vec3 jointPosition = extractTranslation(state.getTransform()); glm::vec3 jointVector = endPosition - jointPosition; glm::quat oldCombinedRotation = state.getRotationInModelFrame(); glm::quat combinedDelta; @@ -1303,7 +1303,7 @@ bool Model::setJointPositionInModelFrame(int jointIndex, const glm::vec3& positi for (int k = j - 1; k > 0; k--) { int index = freeLineage.at(k); updateJointState(index); - positionSum += extractTranslation(_jointStates.at(index).getTransformInModelFrame()); + positionSum += extractTranslation(_jointStates.at(index).getTransform()); } glm::vec3 projectedCenterOfMass = glm::cross(jointVector, glm::cross(positionSum / (j - 1.0f) - jointPosition, jointVector)); @@ -1998,7 +1998,7 @@ void JointState::copyState(const JointState& state) { // DO NOT copy _fbxJoint } -void JointState::computeTransformInModelFrame(const glm::mat4& parentTransform) { +void JointState::computeTransform(const glm::mat4& parentTransform) { glm::quat modifiedRotation = _fbxJoint->preRotation * _rotationInParentFrame * _fbxJoint->postRotation; glm::mat4 modifiedTransform = _fbxJoint->preTransform * glm::mat4_cast(modifiedRotation) * _fbxJoint->postTransform; _transform = parentTransform * glm::translate(_fbxJoint->translation) * modifiedTransform; diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 955207445b..2dabd208af 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -40,8 +40,8 @@ public: void copyState(const JointState& state); - void computeTransformInModelFrame(const glm::mat4& parentTransform); - const glm::mat4& getTransformInModelFrame() const { return _transform; } + void computeTransform(const glm::mat4& parentTransform); + const glm::mat4& getTransform() const { return _transform; } glm::quat getRotationInModelFrame() const { return _rotation; } glm::vec3 getPositionInModelFrame() const { return extractTranslation(_transform); } From 4a3fbfcdeec04379f133f4136d3b6138311d65d0 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 4 Jun 2014 13:34:58 -0700 Subject: [PATCH 20/29] getRotationInModelFrame -> getRotation --- interface/src/avatar/SkeletonModel.cpp | 6 +++--- interface/src/renderer/Model.cpp | 14 +++++++------- interface/src/renderer/Model.h | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index e689deb0a8..c2e4c47a3f 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -148,7 +148,7 @@ void SkeletonModel::applyHandPositionInModelFrame(int jointIndex, const glm::vec return; } JointState& state = _jointStates[jointIndex]; - glm::quat handRotation = state.getRotationInModelFrame(); + glm::quat handRotation = state.getRotation(); // align hand with forearm float sign = (jointIndex == geometry.rightHandJointIndex) ? 1.0f : -1.0f; @@ -267,7 +267,7 @@ void SkeletonModel::renderJointConstraints(int jointIndex) { glPushMatrix(); glTranslatef(position.x, position.y, position.z); - glm::quat parentRotation = (joint.parentIndex == -1) ? _rotation : _rotation * _jointStates.at(joint.parentIndex).getRotationInModelFrame(); + glm::quat parentRotation = (joint.parentIndex == -1) ? _rotation : _rotation * _jointStates.at(joint.parentIndex).getRotation(); glm::vec3 rotationAxis = glm::axis(parentRotation); glRotatef(glm::degrees(glm::angle(parentRotation)), rotationAxis.x, rotationAxis.y, rotationAxis.z); float fanScale = directionSize * 0.75f; @@ -300,7 +300,7 @@ void SkeletonModel::renderJointConstraints(int jointIndex) { } glPopMatrix(); - renderOrientationDirections(position, _rotation * jointState.getRotationInModelFrame(), directionSize); + renderOrientationDirections(position, _rotation * jointState.getRotation(), directionSize); jointIndex = joint.parentIndex; } while (jointIndex != -1 && geometry.joints.at(jointIndex).isFree); diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 8206129c5b..305ad6753e 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -734,7 +734,7 @@ bool Model::getJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) co if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return false; } - rotation = _rotation * _jointStates[jointIndex].getRotationInModelFrame(); + rotation = _rotation * _jointStates[jointIndex].getRotation(); return true; } @@ -742,7 +742,7 @@ bool Model::getJointCombinedRotation(int jointIndex, glm::quat& rotation) const if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return false; } - rotation = _rotation * _jointStates[jointIndex].getRotationInModelFrame(); + rotation = _rotation * _jointStates[jointIndex].getRotation(); return true; } @@ -958,7 +958,7 @@ void Model::updateShapePositions() { const JointState& state = _jointStates[i]; const FBXJoint& joint = state.getFBXJoint(); // shape position and rotation need to be in world-frame - glm::quat stateRotation = state.getRotationInModelFrame(); + glm::quat stateRotation = state.getRotation(); glm::vec3 shapeOffset = uniformScale * (stateRotation * joint.shapePosition); glm::vec3 worldPosition = _translation + _rotation * (state.getPositionInModelFrame() + shapeOffset); Shape* shape = _jointShapes[i]; @@ -1269,9 +1269,9 @@ bool Model::setJointPositionInModelFrame(int jointIndex, const glm::vec3& positi JointState& state = _jointStates[jointIndex]; // TODO: figure out what this is trying to do and combine it into one JointState method - endRotation = state.getRotationInModelFrame(); + endRotation = state.getRotation(); state.applyRotationDeltaInModelFrame(rotation * glm::inverse(endRotation), true, priority); - endRotation = state.getRotationInModelFrame(); + endRotation = state.getRotation(); } // then, we go from the joint upwards, rotating the end as close as possible to the target @@ -1285,7 +1285,7 @@ bool Model::setJointPositionInModelFrame(int jointIndex, const glm::vec3& positi } glm::vec3 jointPosition = extractTranslation(state.getTransform()); glm::vec3 jointVector = endPosition - jointPosition; - glm::quat oldCombinedRotation = state.getRotationInModelFrame(); + glm::quat oldCombinedRotation = state.getRotation(); glm::quat combinedDelta; float combinedWeight; if (useRotation) { @@ -1315,7 +1315,7 @@ bool Model::setJointPositionInModelFrame(int jointIndex, const glm::vec3& positi } } state.applyRotationDeltaInModelFrame(combinedDelta, true, priority); - glm::quat actualDelta = state.getRotationInModelFrame() * glm::inverse(oldCombinedRotation); + glm::quat actualDelta = state.getRotation() * glm::inverse(oldCombinedRotation); endPosition = actualDelta * jointVector + jointPosition; if (useRotation) { endRotation = actualDelta * endRotation; diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 2dabd208af..23d40bb29e 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -43,7 +43,7 @@ public: void computeTransform(const glm::mat4& parentTransform); const glm::mat4& getTransform() const { return _transform; } - glm::quat getRotationInModelFrame() const { return _rotation; } + glm::quat getRotation() const { return _rotation; } glm::vec3 getPositionInModelFrame() const { return extractTranslation(_transform); } /// \return rotation from bind to model frame From d8f5e10947bfe2ccbc0cdb19cb79523f92d89f74 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 4 Jun 2014 13:36:54 -0700 Subject: [PATCH 21/29] getPositionInModelFrame -> getPosition --- interface/src/avatar/SkeletonModel.cpp | 2 +- interface/src/renderer/Model.cpp | 8 ++++---- interface/src/renderer/Model.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index c2e4c47a3f..3792ed531b 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -263,7 +263,7 @@ void SkeletonModel::renderJointConstraints(int jointIndex) { do { const FBXJoint& joint = geometry.joints.at(jointIndex); const JointState& jointState = _jointStates.at(jointIndex); - glm::vec3 position = _rotation * jointState.getPositionInModelFrame() + _translation; + glm::vec3 position = _rotation * jointState.getPosition() + _translation; glPushMatrix(); glTranslatef(position.x, position.y, position.z); diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 305ad6753e..65b618deba 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -718,7 +718,7 @@ bool Model::getJointPositionInWorldFrame(int jointIndex, glm::vec3& position) co if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return false; } - position = _translation + _rotation * _jointStates[jointIndex].getPositionInModelFrame(); + position = _translation + _rotation * _jointStates[jointIndex].getPosition(); return true; } @@ -960,7 +960,7 @@ void Model::updateShapePositions() { // shape position and rotation need to be in world-frame glm::quat stateRotation = state.getRotation(); glm::vec3 shapeOffset = uniformScale * (stateRotation * joint.shapePosition); - glm::vec3 worldPosition = _translation + _rotation * (state.getPositionInModelFrame() + shapeOffset); + glm::vec3 worldPosition = _translation + _rotation * (state.getPosition() + shapeOffset); Shape* shape = _jointShapes[i]; shape->setPosition(worldPosition); shape->setRotation(_rotation * stateRotation * joint.shapeRotation); @@ -985,12 +985,12 @@ bool Model::findRayIntersection(const glm::vec3& origin, const glm::vec3& direct float radiusScale = extractUniformScale(_scale); for (int i = 0; i < _jointStates.size(); i++) { const FBXJoint& joint = geometry.joints[i]; - glm::vec3 end = _translation + _rotation * _jointStates[i].getPositionInModelFrame(); + glm::vec3 end = _translation + _rotation * _jointStates[i].getPosition(); float endRadius = joint.boneRadius * radiusScale; glm::vec3 start = end; float startRadius = joint.boneRadius * radiusScale; if (joint.parentIndex != -1) { - start = _translation + _rotation * _jointStates[joint.parentIndex].getPositionInModelFrame(); + start = _translation + _rotation * _jointStates[joint.parentIndex].getPosition(); startRadius = geometry.joints[joint.parentIndex].boneRadius * radiusScale; } // for now, use average of start and end radii diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 23d40bb29e..1edebc00e0 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -44,7 +44,7 @@ public: const glm::mat4& getTransform() const { return _transform; } glm::quat getRotation() const { return _rotation; } - glm::vec3 getPositionInModelFrame() const { return extractTranslation(_transform); } + glm::vec3 getPosition() const { return extractTranslation(_transform); } /// \return rotation from bind to model frame glm::quat getRotationFromBindToModelFrame() const; From b3cabb8156e9af740dd3f97387e0c905cf111e8d Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 4 Jun 2014 13:43:15 -0700 Subject: [PATCH 22/29] applyRotationDeltaInModelFrame -> applyRotationDelta --- interface/src/avatar/SkeletonModel.cpp | 2 +- interface/src/renderer/Model.cpp | 7 ++++--- interface/src/renderer/Model.h | 3 ++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 3792ed531b..529d2b43dc 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -152,7 +152,7 @@ void SkeletonModel::applyHandPositionInModelFrame(int jointIndex, const glm::vec // align hand with forearm float sign = (jointIndex == geometry.rightHandJointIndex) ? 1.0f : -1.0f; - state.applyRotationDeltaInModelFrame(rotationBetween(handRotation * glm::vec3(-sign, 0.0f, 0.0f), forearmVector), true, PALM_PRIORITY); + state.applyRotationDelta(rotationBetween(handRotation * glm::vec3(-sign, 0.0f, 0.0f), forearmVector), true, PALM_PRIORITY); } void SkeletonModel::applyPalmDataInModelFrame(int jointIndex, PalmData& palm) { diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 65b618deba..26376e6feb 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1270,7 +1270,7 @@ bool Model::setJointPositionInModelFrame(int jointIndex, const glm::vec3& positi // TODO: figure out what this is trying to do and combine it into one JointState method endRotation = state.getRotation(); - state.applyRotationDeltaInModelFrame(rotation * glm::inverse(endRotation), true, priority); + state.applyRotationDelta(rotation * glm::inverse(endRotation), true, priority); endRotation = state.getRotation(); } @@ -1314,7 +1314,7 @@ bool Model::setJointPositionInModelFrame(int jointIndex, const glm::vec3& positi 1.0f / (combinedWeight + 1.0f)); } } - state.applyRotationDeltaInModelFrame(combinedDelta, true, priority); + state.applyRotationDelta(combinedDelta, true, priority); glm::quat actualDelta = state.getRotation() * glm::inverse(oldCombinedRotation); endPosition = actualDelta * jointVector + jointPosition; if (useRotation) { @@ -2031,7 +2031,8 @@ void JointState::clearTransformTranslation() { _transform[3][2] = 0.0f; } -void JointState::applyRotationDeltaInModelFrame(const glm::quat& delta, bool constrain, float priority) { +void JointState::applyRotationDelta(const glm::quat& delta, bool constrain, float priority) { + // NOTE: delta is in jointParent-frame assert(_fbxJoint != NULL); if (priority < _animationPriority) { return; diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 1edebc00e0..409f307363 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -49,7 +49,8 @@ public: /// \return rotation from bind to model frame glm::quat getRotationFromBindToModelFrame() const; - void applyRotationDeltaInModelFrame(const glm::quat& delta, bool constrain = true, float priority = 1.0f); + /// \param delta is in the jointParent-frame + void applyRotationDelta(const glm::quat& delta, bool constrain = true, float priority = 1.0f); const glm::vec3& getDefaultTranslationInParentFrame() const; From 971268d4f2f8b429a6ae1aaf22a5bb3e71bfd347 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 4 Jun 2014 13:46:08 -0700 Subject: [PATCH 23/29] setRotationInModelFrame -> setRotation --- interface/src/avatar/SkeletonModel.cpp | 10 +++++----- interface/src/renderer/Model.cpp | 2 +- interface/src/renderer/Model.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 529d2b43dc..63a2859366 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -46,7 +46,7 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { int jointIndex = geometry.humanIKJointIndices.at(humanIKJointIndex); if (jointIndex != -1) { JointState& state = _jointStates[jointIndex]; - state.setRotationInModelFrame(prioVR->getJointRotations().at(i), PALM_PRIORITY); + state.setRotation(prioVR->getJointRotations().at(i), PALM_PRIORITY); } } return; @@ -198,7 +198,7 @@ void SkeletonModel::applyPalmDataInModelFrame(int jointIndex, PalmData& palm) { geometry.joints.at(jointIndex).distanceToParent * extractUniformScale(_scale), glm::quat(), false, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY); JointState& parentState = _jointStates[parentJointIndex]; - parentState.setRotationInModelFrame(palmRotation, PALM_PRIORITY); + parentState.setRotation(palmRotation, PALM_PRIORITY); // lock hand to forearm by slamming its rotation (in parent-frame) to identity _jointStates[jointIndex]._rotationInParentFrame = glm::quat(); } else { @@ -363,13 +363,13 @@ void SkeletonModel::setHandPositionInModelFrame(int jointIndex, const glm::vec3& glm::quat shoulderRotation = rotationBetween(forwardVector, elbowPosition - shoulderPosition); JointState& shoulderState = _jointStates[shoulderJointIndex]; - shoulderState.setRotationInModelFrame(shoulderRotation, PALM_PRIORITY); + shoulderState.setRotation(shoulderRotation, PALM_PRIORITY); JointState& elbowState = _jointStates[elbowJointIndex]; - elbowState.setRotationInModelFrame(rotationBetween(shoulderRotation * forwardVector, wristPosition - elbowPosition) * shoulderRotation, PALM_PRIORITY); + elbowState.setRotation(rotationBetween(shoulderRotation * forwardVector, wristPosition - elbowPosition) * shoulderRotation, PALM_PRIORITY); JointState& handState = _jointStates[jointIndex]; - handState.setRotationInModelFrame(rotation, PALM_PRIORITY); + handState.setRotation(rotation, PALM_PRIORITY); } bool SkeletonModel::getLeftHandPosition(glm::vec3& position) const { diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 26376e6feb..4f2bb79faf 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -2017,7 +2017,7 @@ void JointState::restoreRotation(float fraction, float priority) { } } -void JointState::setRotationInModelFrame(const glm::quat& rotation, float priority) { +void JointState::setRotation(const glm::quat& rotation, float priority) { assert(_fbxJoint != NULL); if (priority >= _animationPriority) { _rotationInParentFrame = _rotationInParentFrame * glm::inverse(_rotation) * rotation * glm::inverse(_fbxJoint->inverseBindRotation); diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 409f307363..7a0e6b1dbb 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -59,7 +59,7 @@ public: /// \param rotation is from bind- to model-frame /// computes and sets new _rotationInParentFrame /// NOTE: the JointState's model-frame transform/rotation are NOT updated! - void setRotationInModelFrame(const glm::quat& rotation, float priority); + void setRotation(const glm::quat& rotation, float priority); void clearTransformTranslation(); From 3af4b1b33398fd90daf6d007b6448758c5aad255 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 4 Jun 2014 13:51:43 -0700 Subject: [PATCH 24/29] getJointPositionInModelFrame -> getJointPosition --- interface/src/avatar/SkeletonModel.cpp | 6 +++--- interface/src/renderer/Model.cpp | 4 +++- interface/src/renderer/Model.h | 6 ++++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 63a2859366..008ea65557 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -140,8 +140,8 @@ void SkeletonModel::applyHandPositionInModelFrame(int jointIndex, const glm::vec const FBXGeometry& geometry = _geometry->getFBXGeometry(); glm::vec3 handPosition, elbowPosition; - getJointPositionInModelFrame(jointIndex, handPosition); - getJointPositionInModelFrame(geometry.joints.at(jointIndex).parentIndex, elbowPosition); + getJointPosition(jointIndex, handPosition); + getJointPosition(geometry.joints.at(jointIndex).parentIndex, elbowPosition); glm::vec3 forearmVector = handPosition - elbowPosition; float forearmLength = glm::length(forearmVector); if (forearmLength < EPSILON) { @@ -317,7 +317,7 @@ void SkeletonModel::setHandPositionInModelFrame(int jointIndex, const glm::vec3& } int shoulderJointIndex = geometry.joints.at(elbowJointIndex).parentIndex; glm::vec3 shoulderPosition; - if (!getJointPositionInModelFrame(shoulderJointIndex, shoulderPosition)) { + if (!getJointPosition(shoulderJointIndex, shoulderPosition)) { return; } // precomputed lengths diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 4f2bb79faf..66be7e4bfc 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -718,14 +718,16 @@ bool Model::getJointPositionInWorldFrame(int jointIndex, glm::vec3& position) co if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return false; } + // position is in world-frame position = _translation + _rotation * _jointStates[jointIndex].getPosition(); return true; } -bool Model::getJointPositionInModelFrame(int jointIndex, glm::vec3& position) const { +bool Model::getJointPosition(int jointIndex, glm::vec3& position) const { if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return false; } + // position is in model-frame position = extractTranslation(_jointStates[jointIndex].getTransform()); return true; } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 7a0e6b1dbb..d6721d2bad 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -164,11 +164,13 @@ public: int getLastFreeJointIndex(int jointIndex) const; bool getJointPositionInWorldFrame(int jointIndex, glm::vec3& position) const; - bool getJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const; bool getJointCombinedRotation(int jointIndex, glm::quat& rotation) const; - bool getJointPositionInModelFrame(int jointIndex, glm::vec3& position) const; + /// \param jointIndex index of joint in model structure + /// \param position[out] position of joint in model-frame + /// \return true if joint exists + bool getJointPosition(int jointIndex, glm::vec3& position) const; QStringList getJointNames() const; From ccfd620c842b91850a0617b21860b669f50f417a Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 4 Jun 2014 13:56:37 -0700 Subject: [PATCH 25/29] setJointPositionInModelFrame -> setJointPosition --- interface/src/avatar/SkeletonModel.cpp | 6 +++--- interface/src/renderer/Model.cpp | 4 ++-- interface/src/renderer/Model.h | 10 +++++++++- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 008ea65557..385f11e185 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -136,7 +136,7 @@ void SkeletonModel::applyHandPositionInModelFrame(int jointIndex, const glm::vec if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return; } - setJointPositionInModelFrame(jointIndex, position, glm::quat(), false, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY); + setJointPosition(jointIndex, position, glm::quat(), false, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY); const FBXGeometry& geometry = _geometry->getFBXGeometry(); glm::vec3 handPosition, elbowPosition; @@ -194,7 +194,7 @@ void SkeletonModel::applyPalmDataInModelFrame(int jointIndex, PalmData& palm) { } else if (Menu::getInstance()->isOptionChecked(MenuOption::AlignForearmsWithWrists)) { glm::vec3 forearmVector = palmRotation * glm::vec3(sign, 0.0f, 0.0f); - setJointPositionInModelFrame(parentJointIndex, palmPosition + forearmVector * + setJointPosition(parentJointIndex, palmPosition + forearmVector * geometry.joints.at(jointIndex).distanceToParent * extractUniformScale(_scale), glm::quat(), false, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY); JointState& parentState = _jointStates[parentJointIndex]; @@ -202,7 +202,7 @@ void SkeletonModel::applyPalmDataInModelFrame(int jointIndex, PalmData& palm) { // lock hand to forearm by slamming its rotation (in parent-frame) to identity _jointStates[jointIndex]._rotationInParentFrame = glm::quat(); } else { - setJointPositionInModelFrame(jointIndex, palmPosition, palmRotation, + setJointPosition(jointIndex, palmPosition, palmRotation, true, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY); } } diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 66be7e4bfc..375927483a 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1246,7 +1246,7 @@ void Model::updateJointState(int index) { } } -bool Model::setJointPositionInModelFrame(int jointIndex, const glm::vec3& position, const glm::quat& rotation, bool useRotation, +bool Model::setJointPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation, bool useRotation, int lastFreeIndex, bool allIntermediatesFree, const glm::vec3& alignment, float priority) { if (jointIndex == -1 || _jointStates.isEmpty()) { return false; @@ -1486,7 +1486,7 @@ void Model::applyCollision(CollisionInfo& collision) { // transform into model-frame glm::vec3 newEnd = glm::inverse(_rotation) * (start + glm::angleAxis(angle, axis) * (end - start) - _translation); // try to move it - setJointPositionInModelFrame(jointIndex, newEnd, glm::quat(), false, -1, true); + setJointPosition(jointIndex, newEnd, glm::quat(), false, -1, true); } } } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index d6721d2bad..e73f3573f7 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -257,7 +257,15 @@ protected: /// Updates the state of the joint at the specified index. virtual void updateJointState(int index); - bool setJointPositionInModelFrame(int jointIndex, const glm::vec3& translation, const glm::quat& rotation = glm::quat(), + /// \param jointIndex index of joint in model structure + /// \param position position of joint in model-frame + /// \param rotation rotation of joint in model-frame + /// \param useRotation false if rotation should be ignored + /// \param lastFreeIndex + /// \param allIntermediatesFree + /// \param alignment + /// \return true if joint exists + bool setJointPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation = glm::quat(), bool useRotation = false, int lastFreeIndex = -1, bool allIntermediatesFree = false, const glm::vec3& alignment = glm::vec3(0.0f, -1.0f, 0.0f), float priority = 1.0f); From 323fa70cf38cbb1e83b40b47134b29d1d9fe5629 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 4 Jun 2014 14:03:29 -0700 Subject: [PATCH 26/29] remove last of "InModelFrame" qualifiers --- interface/src/avatar/SkeletonModel.cpp | 18 ++++++++++-------- interface/src/avatar/SkeletonModel.h | 12 +++++++++--- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 385f11e185..278b70bce4 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -63,19 +63,20 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { if (_owningAvatar->getHandState() == HAND_STATE_NULL) { restoreRightHandPosition(HAND_RESTORATION_RATE, PALM_PRIORITY); } else { + // transform into model-frame glm::vec3 handPosition = glm::inverse(_rotation) * (_owningAvatar->getHandPosition() - _translation); - applyHandPositionInModelFrame(geometry.rightHandJointIndex, handPosition); + applyHandPosition(geometry.rightHandJointIndex, handPosition); } restoreLeftHandPosition(HAND_RESTORATION_RATE, PALM_PRIORITY); } else if (leftPalmIndex == rightPalmIndex) { // right hand only - applyPalmDataInModelFrame(geometry.rightHandJointIndex, hand->getPalms()[leftPalmIndex]); + applyPalmData(geometry.rightHandJointIndex, hand->getPalms()[leftPalmIndex]); restoreLeftHandPosition(HAND_RESTORATION_RATE, PALM_PRIORITY); } else { - applyPalmDataInModelFrame(geometry.leftHandJointIndex, hand->getPalms()[leftPalmIndex]); - applyPalmDataInModelFrame(geometry.rightHandJointIndex, hand->getPalms()[rightPalmIndex]); + applyPalmData(geometry.leftHandJointIndex, hand->getPalms()[leftPalmIndex]); + applyPalmData(geometry.rightHandJointIndex, hand->getPalms()[rightPalmIndex]); } } @@ -132,10 +133,11 @@ bool operator<(const IndexValue& firstIndex, const IndexValue& secondIndex) { return firstIndex.value < secondIndex.value; } -void SkeletonModel::applyHandPositionInModelFrame(int jointIndex, const glm::vec3& position) { +void SkeletonModel::applyHandPosition(int jointIndex, const glm::vec3& position) { if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return; } + // NOTE: 'position' is in model-frame setJointPosition(jointIndex, position, glm::quat(), false, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY); const FBXGeometry& geometry = _geometry->getFBXGeometry(); @@ -155,7 +157,7 @@ void SkeletonModel::applyHandPositionInModelFrame(int jointIndex, const glm::vec state.applyRotationDelta(rotationBetween(handRotation * glm::vec3(-sign, 0.0f, 0.0f), forearmVector), true, PALM_PRIORITY); } -void SkeletonModel::applyPalmDataInModelFrame(int jointIndex, PalmData& palm) { +void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) { if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return; } @@ -190,7 +192,7 @@ void SkeletonModel::applyPalmDataInModelFrame(int jointIndex, PalmData& palm) { // set hand position, rotation glm::vec3 palmPosition = inverseRotation * (palm.getPosition() - _translation); if (Menu::getInstance()->isOptionChecked(MenuOption::AlternateIK)) { - setHandPositionInModelFrame(jointIndex, palmPosition, palmRotation); + setHandPosition(jointIndex, palmPosition, palmRotation); } else if (Menu::getInstance()->isOptionChecked(MenuOption::AlignForearmsWithWrists)) { glm::vec3 forearmVector = palmRotation * glm::vec3(sign, 0.0f, 0.0f); @@ -308,7 +310,7 @@ void SkeletonModel::renderJointConstraints(int jointIndex) { glLineWidth(1.0f); } -void SkeletonModel::setHandPositionInModelFrame(int jointIndex, const glm::vec3& position, const glm::quat& rotation) { +void SkeletonModel::setHandPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation) { // this algorithm is from sample code from sixense const FBXGeometry& geometry = _geometry->getFBXGeometry(); int elbowJointIndex = geometry.joints.at(jointIndex).parentIndex; diff --git a/interface/src/avatar/SkeletonModel.h b/interface/src/avatar/SkeletonModel.h index 092722fd40..4335dfc3ff 100644 --- a/interface/src/avatar/SkeletonModel.h +++ b/interface/src/avatar/SkeletonModel.h @@ -91,9 +91,11 @@ public: protected: - void applyHandPositionInModelFrame(int jointIndex, const glm::vec3& position); + /// \param jointIndex index of joint in model + /// \param position position of joint in model-frame + void applyHandPosition(int jointIndex, const glm::vec3& position); - void applyPalmDataInModelFrame(int jointIndex, PalmData& palm); + void applyPalmData(int jointIndex, PalmData& palm); /// Updates the state of the joint at the specified index. virtual void updateJointState(int index); @@ -105,7 +107,11 @@ protected: private: void renderJointConstraints(int jointIndex); - void setHandPositionInModelFrame(int jointIndex, const glm::vec3& position, const glm::quat& rotation); + + /// \param jointIndex index of joint in model + /// \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); Avatar* _owningAvatar; }; From 212ac13802ddad002bc63aa31838e114ef8c4c6a Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 4 Jun 2014 14:10:28 -0700 Subject: [PATCH 27/29] setRotation -> setJointRotationFromBindFrame --- interface/src/avatar/SkeletonModel.cpp | 10 +++++----- interface/src/renderer/Model.cpp | 2 +- interface/src/renderer/Model.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 278b70bce4..58151d25ab 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -46,7 +46,7 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { int jointIndex = geometry.humanIKJointIndices.at(humanIKJointIndex); if (jointIndex != -1) { JointState& state = _jointStates[jointIndex]; - state.setRotation(prioVR->getJointRotations().at(i), PALM_PRIORITY); + state.setRotationFromBindFrame(prioVR->getJointRotations().at(i), PALM_PRIORITY); } } return; @@ -200,7 +200,7 @@ void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) { geometry.joints.at(jointIndex).distanceToParent * extractUniformScale(_scale), glm::quat(), false, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY); JointState& parentState = _jointStates[parentJointIndex]; - parentState.setRotation(palmRotation, PALM_PRIORITY); + parentState.setRotationFromBindFrame(palmRotation, PALM_PRIORITY); // lock hand to forearm by slamming its rotation (in parent-frame) to identity _jointStates[jointIndex]._rotationInParentFrame = glm::quat(); } else { @@ -365,13 +365,13 @@ void SkeletonModel::setHandPosition(int jointIndex, const glm::vec3& position, c glm::quat shoulderRotation = rotationBetween(forwardVector, elbowPosition - shoulderPosition); JointState& shoulderState = _jointStates[shoulderJointIndex]; - shoulderState.setRotation(shoulderRotation, PALM_PRIORITY); + shoulderState.setRotationFromBindFrame(shoulderRotation, PALM_PRIORITY); JointState& elbowState = _jointStates[elbowJointIndex]; - elbowState.setRotation(rotationBetween(shoulderRotation * forwardVector, wristPosition - elbowPosition) * shoulderRotation, PALM_PRIORITY); + elbowState.setRotationFromBindFrame(rotationBetween(shoulderRotation * forwardVector, wristPosition - elbowPosition) * shoulderRotation, PALM_PRIORITY); JointState& handState = _jointStates[jointIndex]; - handState.setRotation(rotation, PALM_PRIORITY); + handState.setRotationFromBindFrame(rotation, PALM_PRIORITY); } bool SkeletonModel::getLeftHandPosition(glm::vec3& position) const { diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 375927483a..beab69ecfb 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -2019,7 +2019,7 @@ void JointState::restoreRotation(float fraction, float priority) { } } -void JointState::setRotation(const glm::quat& rotation, float priority) { +void JointState::setRotationFromBindFrame(const glm::quat& rotation, float priority) { assert(_fbxJoint != NULL); if (priority >= _animationPriority) { _rotationInParentFrame = _rotationInParentFrame * glm::inverse(_rotation) * rotation * glm::inverse(_fbxJoint->inverseBindRotation); diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index e73f3573f7..cb91d74b3b 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -59,7 +59,7 @@ public: /// \param rotation is from bind- to model-frame /// computes and sets new _rotationInParentFrame /// NOTE: the JointState's model-frame transform/rotation are NOT updated! - void setRotation(const glm::quat& rotation, float priority); + void setRotationFromBindFrame(const glm::quat& rotation, float priority); void clearTransformTranslation(); From f19b562e881ce84fec020a83ebc3398060dd9ab1 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 4 Jun 2014 14:17:39 -0700 Subject: [PATCH 28/29] add JointState::setRotation(rotModelFrame) --- interface/src/renderer/Model.cpp | 8 +++++--- interface/src/renderer/Model.h | 3 +++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index beab69ecfb..bc383149d8 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1270,9 +1270,7 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& position, const gl if (useRotation) { JointState& state = _jointStates[jointIndex]; - // TODO: figure out what this is trying to do and combine it into one JointState method - endRotation = state.getRotation(); - state.applyRotationDelta(rotation * glm::inverse(endRotation), true, priority); + state.setRotation(rotation, true, priority); endRotation = state.getRotation(); } @@ -2033,6 +2031,10 @@ void JointState::clearTransformTranslation() { _transform[3][2] = 0.0f; } +void JointState::setRotation(const glm::quat& rotation, bool constrain, float priority) { + applyRotationDelta(rotation * glm::inverse(_rotation), true, priority); +} + void JointState::applyRotationDelta(const glm::quat& delta, bool constrain, float priority) { // NOTE: delta is in jointParent-frame assert(_fbxJoint != NULL); diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index cb91d74b3b..7d7406fc42 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -49,6 +49,9 @@ public: /// \return rotation from bind to model frame glm::quat getRotationFromBindToModelFrame() const; + /// \param rotation rotation of joint in model-frame + void setRotation(const glm::quat& rotation, bool constrain, float priority); + /// \param delta is in the jointParent-frame void applyRotationDelta(const glm::quat& delta, bool constrain = true, float priority = 1.0f); From e1cb88471f655d54d5da4c71333c99027345f8d2 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 4 Jun 2014 14:19:45 -0700 Subject: [PATCH 29/29] add a comment --- interface/src/renderer/Model.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index bc383149d8..ca340808e5 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -2020,6 +2020,7 @@ void JointState::restoreRotation(float fraction, float priority) { void JointState::setRotationFromBindFrame(const glm::quat& rotation, float priority) { assert(_fbxJoint != NULL); if (priority >= _animationPriority) { + // rotation is from bind- to model-frame _rotationInParentFrame = _rotationInParentFrame * glm::inverse(_rotation) * rotation * glm::inverse(_fbxJoint->inverseBindRotation); _animationPriority = priority; }