From 280a4c0e56ff0ce2119ffc502c431298f3c72b82 Mon Sep 17 00:00:00 2001 From: Mike Kremer Date: Wed, 4 Jan 2012 15:16:03 +0000 Subject: [PATCH] Made root joint translatable. Added some documentation. git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@13151 383ad7c9-94d9-4d36-a494-682f7c89f535 --- SkeletonEditingScripting.cc | 280 +++++++++++++++++++----------------- 1 file changed, 149 insertions(+), 131 deletions(-) diff --git a/SkeletonEditingScripting.cc b/SkeletonEditingScripting.cc index 86295bd..ea9ade0 100644 --- a/SkeletonEditingScripting.cc +++ b/SkeletonEditingScripting.cc @@ -342,150 +342,168 @@ void SkeletonEditingPlugin::transformJoint(int _objectId, int _jointId, if (_matrix(0, 3) == 0 && _matrix(1, 3) == 0 && _matrix(2, 3) == 0) // no translation return; - if (!joint->parent()) - return; - - // init params - bool parentIsNotBranch = (joint->parent()->size() == 1); - bool hasOneChild = (joint->size() == 1); - ACG::Vec3d oldParentAxis(0.0, 0.0, 0.0); - ACG::Vec3d oldJointAxis(0.0, 0.0, 0.0); - ACG::Vec3d transParentAxis(0.0, 0.0, 0.0); - ACG::Vec3d transJointAxis(0.0, 0.0, 0.0); - ACG::Vec3d parentRotAxis(0.0, 0.0, 0.0); - ACG::Vec3d jointRotAxis(0.0, 0.0, 0.0); - double parentRotAngle = 0.0; - double jointRotAngle = 0.0; - - // get the original parent axis: parent joint -----> current joint - oldParentAxis = activePose->localTranslation(_jointId); - // get the original joint axis: current joint -----> child joint - if (hasOneChild) - oldJointAxis = activePose->localTranslation(joint->child(0)->id()); - - // store the joint axes of all animations before the translation of the current joint - // so that the rotations can be calculated for the animation poses - std::vector oldAnimJoint, oldAnimParent; - for (unsigned int a = 0; a < skeleton->animationCount(); ++a) { - for (unsigned int iFrame = 0; iFrame - < skeleton->animation(a)->frameCount(); iFrame++) { - Skeleton::Pose* pose = skeleton->animation(a)->pose(iFrame); - - if (hasOneChild) - oldAnimJoint.push_back( - pose->localTranslation(joint->child(0)->id())); - - oldAnimParent.push_back(pose->localTranslation(_jointId)); + if (joint->isRoot()) { + + /* + * Change translation of root joint. + */ + + transformer.translateJoint(joint, ACG::Vec3d(_matrix(0, 3), _matrix(1, 3), _matrix(2, 3)), true); + + } else { + + /* + * Change translation of non-root joint. + * + * In these cases, the rotation of the coordinate frame of the parent + * joint (unless it is not a branching joint) as well as the + * the rotation of the coordinate frame of the current joint have to be + * corrected in the following way: + * + * We compute the rotation of the affected joints' coordinate system + * such that the local(!) translation of the respective child + * joint remains constant. So, in 2D, consider configuration + * A --> B --> C, where C is a child of B is a child of A. + * If C has translation (2, 0) and B has translation (3,5), then, after + * global translation of B, the coordinate frames of A and B have to be rotated + * such that the joint axes remain constant, so B lies on the line (0,0) + x*(3,5) + * with respect to A's coordinate system and C lies somewhere on the line (0,0) + y*(2,0) + * with respect to B's coordinate system. + * + */ + + // init params + bool parentIsNotBranch = (joint->parent()->size() == 1); + bool hasOneChild = (joint->size() == 1); + ACG::Vec3d oldParentAxis(0.0, 0.0, 0.0); + ACG::Vec3d oldJointAxis(0.0, 0.0, 0.0); + ACG::Vec3d transParentAxis(0.0, 0.0, 0.0); + ACG::Vec3d transJointAxis(0.0, 0.0, 0.0); + ACG::Vec3d parentRotAxis(0.0, 0.0, 0.0); + ACG::Vec3d jointRotAxis(0.0, 0.0, 0.0); + double parentRotAngle = 0.0; + double jointRotAngle = 0.0; + + // get the original parent axis: parent joint -----> current joint + oldParentAxis = activePose->localTranslation(_jointId); + // get the original joint axis: current joint -----> child joint + if (hasOneChild) + oldJointAxis = activePose->localTranslation(joint->child(0)->id()); + + // store the joint axes of all animations before the translation of the current joint + // so that the rotations can be calculated for the animation poses + std::vector oldAnimJoint, oldAnimParent; + for (unsigned int a = 0; a < skeleton->animationCount(); ++a) { + for (unsigned int iFrame = 0; iFrame < skeleton->animation(a)->frameCount(); iFrame++) { + Skeleton::Pose* pose = skeleton->animation(a)->pose(iFrame); + + if (hasOneChild) + oldAnimJoint.push_back(pose->localTranslation(joint->child(0)->id())); + + oldAnimParent.push_back(pose->localTranslation(_jointId)); + } } - } - // translate the joint - transformer.translateJoint(joint, - ACG::Vec3d(_matrix(0, 3), _matrix(1, 3), _matrix(2, 3)), true); + // translate the joint + transformer.translateJoint(joint, ACG::Vec3d(_matrix(0, 3), _matrix(1, 3), _matrix(2, 3)), true); - // get translated parent axis - transParentAxis = activePose->localTranslation(_jointId); + // get translated parent axis + transParentAxis = activePose->localTranslation(_jointId); - if (hasOneChild) { - // get translated joint axis - transJointAxis = activePose->localTranslation(joint->child(0)->id()); - } - - // now calculate the rotation that has to occur for a translation of the joint: + if (hasOneChild) { + // get translated joint axis + transJointAxis = activePose->localTranslation(joint->child(0)->id()); + } - // get the rotation axis and angle between the old and new parent axis - if (!ACG::Geometry::rotationOfTwoVectors(oldParentAxis, - transParentAxis, parentRotAxis, parentRotAngle)) - return; + // now calculate the rotation that has to occur for a translation of the joint: - // get rotation axis and angle between old and new joint axis - if (hasOneChild) { - if (!ACG::Geometry::rotationOfTwoVectors(oldJointAxis, - transJointAxis, jointRotAxis, jointRotAngle)) + // get the rotation axis and angle between the old and new parent axis + if (!ACG::Geometry::rotationOfTwoVectors(oldParentAxis, transParentAxis, parentRotAxis, parentRotAngle)) return; - } - if (parentIsNotBranch) { - // parent rotation matrix - ACG::GLMatrixT parentRotMatrix; - parentRotMatrix.identity(); - parentRotMatrix.rotate(parentRotAngle, parentRotAxis); - - // apply rotation to parent joint - ACG::Matrix4x4d localParent = activePose->localMatrix( - joint->parent()->id()); - localParent *= parentRotMatrix; - activePose->setLocalMatrix(joint->parent()->id(), localParent, false); - } - - if (hasOneChild) { - // joint rotation matrix - ACG::GLMatrixT jointRotMatrix; - jointRotMatrix.identity(); - jointRotMatrix.rotate(jointRotAngle, jointRotAxis); - - // apply current joint - ACG::Matrix4x4d localJoint = activePose->localMatrix(joint->id()); - localJoint *= jointRotMatrix; - activePose->setLocalMatrix(joint->id(), localJoint, false); - } - - // apply rotations to animation - std::vector::iterator jointIt, parentIt; - jointIt = oldAnimJoint.begin(); - parentIt = oldAnimParent.begin(); - for (unsigned int a = 0; a < skeleton->animationCount(); ++a) { - for (unsigned int iFrame = 0; iFrame - < skeleton->animation(a)->frameCount(); iFrame++) { - Skeleton::Pose* pose = skeleton->animation(a)->pose(iFrame); - - // only apply rotation to parent joint if it is not a branch - if (parentIsNotBranch) { - - // get the rotation axis and angle between the old and new parent axis - ACG::Vec3d translatedParent = pose->localTranslation(_jointId); - ACG::Vec3d parentRotAxis(0.0, 0.0, 0.0); - double parentRotAngle = 0.0; - if (!ACG::Geometry::rotationOfTwoVectors(*parentIt, - translatedParent, parentRotAxis, parentRotAngle)) - return; - - // parent rotation matrix - ACG::GLMatrixT parentRotMatrix; - parentRotMatrix.identity(); - parentRotMatrix.rotate(parentRotAngle, parentRotAxis); - - // apply rotation to parent joint - ACG::Matrix4x4d parentMat = - pose->localMatrix(joint->parent()->id()); - parentMat *= parentRotMatrix; - pose->setLocalMatrix(joint->parent()->id(), parentMat, false); - - ++parentIt; - } + // get rotation axis and angle between old and new joint axis + if (hasOneChild) { + if (!ACG::Geometry::rotationOfTwoVectors(oldJointAxis, transJointAxis, jointRotAxis, jointRotAngle)) + return; + } - if (hasOneChild) { - // get rotation axis and angle between old and new joint axis - ACG::Vec3d translatedAxis = pose->localTranslation( - joint->child(0)->id()); - ACG::Vec3d jointRotAxis(0.0, 0.0, 0.0); - double jointRotAngle = 0.0; + if (parentIsNotBranch) { + // parent rotation matrix + ACG::GLMatrixT parentRotMatrix; + parentRotMatrix.identity(); + parentRotMatrix.rotate(parentRotAngle, parentRotAxis); - if (!ACG::Geometry::rotationOfTwoVectors(*jointIt, - translatedAxis, jointRotAxis, jointRotAngle)) - return; + // apply rotation to parent joint + ACG::Matrix4x4d localParent = activePose->localMatrix(joint->parent()->id()); + localParent *= parentRotMatrix; + activePose->setLocalMatrix(joint->parent()->id(), localParent, false); + } - // joint rotation matrix - ACG::GLMatrixT jointRotMatrix; - jointRotMatrix.identity(); - jointRotMatrix.rotate(jointRotAngle, jointRotAxis); + if (hasOneChild) { + // joint rotation matrix + ACG::GLMatrixT jointRotMatrix; + jointRotMatrix.identity(); + jointRotMatrix.rotate(jointRotAngle, jointRotAxis); - // apply rotation to current joint - ACG::Matrix4x4d localMat = pose->localMatrix(joint->id()); - localMat *= jointRotMatrix; - pose->setLocalMatrix(joint->id(), localMat, false); + // apply current joint + ACG::Matrix4x4d localJoint = activePose->localMatrix(joint->id()); + localJoint *= jointRotMatrix; + activePose->setLocalMatrix(joint->id(), localJoint, false); + } - ++jointIt; + // apply rotations to animation + std::vector::iterator jointIt, parentIt; + jointIt = oldAnimJoint.begin(); + parentIt = oldAnimParent.begin(); + for (unsigned int a = 0; a < skeleton->animationCount(); ++a) { + for (unsigned int iFrame = 0; iFrame < skeleton->animation(a)->frameCount(); iFrame++) { + Skeleton::Pose* pose = skeleton->animation(a)->pose(iFrame); + + // only apply rotation to parent joint if it is not a branch + if (parentIsNotBranch) { + + // get the rotation axis and angle between the old and new parent axis + ACG::Vec3d translatedParent = pose->localTranslation(_jointId); + ACG::Vec3d parentRotAxis(0.0, 0.0, 0.0); + double parentRotAngle = 0.0; + if (!ACG::Geometry::rotationOfTwoVectors(*parentIt, translatedParent, parentRotAxis, + parentRotAngle)) + return; + + // parent rotation matrix + ACG::GLMatrixT parentRotMatrix; + parentRotMatrix.identity(); + parentRotMatrix.rotate(parentRotAngle, parentRotAxis); + + // apply rotation to parent joint + ACG::Matrix4x4d parentMat = pose->localMatrix(joint->parent()->id()); + parentMat *= parentRotMatrix; + pose->setLocalMatrix(joint->parent()->id(), parentMat, false); + + ++parentIt; + } + + if (hasOneChild) { + // get rotation axis and angle between old and new joint axis + ACG::Vec3d translatedAxis = pose->localTranslation(joint->child(0)->id()); + ACG::Vec3d jointRotAxis(0.0, 0.0, 0.0); + double jointRotAngle = 0.0; + + if (!ACG::Geometry::rotationOfTwoVectors(*jointIt, translatedAxis, jointRotAxis, jointRotAngle)) + return; + + // joint rotation matrix + ACG::GLMatrixT jointRotMatrix; + jointRotMatrix.identity(); + jointRotMatrix.rotate(jointRotAngle, jointRotAxis); + + // apply rotation to current joint + ACG::Matrix4x4d localMat = pose->localMatrix(joint->id()); + localMat *= jointRotMatrix; + pose->setLocalMatrix(joint->id(), localMat, false); + + ++jointIt; + } } } } -- GitLab