bool util::isDrivenBySplineIK(const MFnIkJoint & iJoint) { // spline IK can drive the starting joint's translate channel but // it has no connection to the translate plug. // we treat the joint as animated in this case. // find the ikHandle node. MPlug msgPlug = iJoint.findPlug("message", false); MPlugArray msgPlugDst; msgPlug.connectedTo(msgPlugDst, false, true); for (unsigned int i = 0; i < msgPlugDst.length(); i++) { MFnDependencyNode ikHandle(msgPlugDst[i].node()); if (!ikHandle.object().hasFn(MFn::kIkHandle)) continue; // find the ikSolver node. MPlug ikSolverPlug = ikHandle.findPlug("ikSolver"); MPlugArray ikSolverDst; ikSolverPlug.connectedTo(ikSolverDst, true, false); for (unsigned int j = 0; j < ikSolverDst.length(); j++) { // return true if the ikSolver is a spline solver. if (ikSolverDst[j].node().hasFn(MFn::kSplineSolver)) { return true; } } } return false; }
// getBindPoseMatrix. // should be a relatively harmless function. // well you're wrong: this is one of the most stupid/difficult things in // Maya: // 1st try: just get the "bindPose"-plug, and use it as matrix: // MFnIkJoint joint(jointPath.node()); // MPlug bindMatrixPlug = joint.findPlug("bindPose"); // MObject bindMatrixObject; // bindMatrixPlug.getValue(bindMatrixObject); // MFnMatrixData matrixData(bindMatrixObject); // MMatrix bindMatrix = matrixData.matrix(); // Looks correct. But isn't. Not only, that we want the local // transform (but that wouldn't be difficult (just look at the // parent...), the bindPose plug seems // to be shared between instances. If a joint is instanced, the // bindMatrix would be the same as for the other instance. Bad luck :( // 2nd try: extract the local-transform out of the bindPose-plug. That's // what is done here. (at least for now. (seen first in // MS' xporttranslator). // Still not the really correct way: it's possible to break the // bindPose-plug. Maya still works, but our exporter doesn't. // 3rd (and correct way): // http://www.greggman.com/pages/mayastuff.htm // // again: not yet very much error-checking... MMatrix BindPoseTool::getBindPoseMatrix(MFnIkJoint joint) const { // get bindPose-plug on joint MPlug tempBindPosePlug = joint.findPlug("bindPose"); MPlugArray mapConnections; tempBindPosePlug.connectedTo(mapConnections, false, true); if (mapConnections.length() != 1) { //cout << "returning currentMatrix" << endl; // certainly not the most correct way of dealing with the problem... return joint.transformation().asMatrix(); } // find the other end. actually we shouldn't call it "bindPosePlug", // but worldTransformPlug (as that's where it enters). // theoretically someone could bind the bindPose to other nodes, // than the bindPose-node. in this case there's a problem. MPlug bindPosePlug = mapConnections[0]; // this node should be a "dagPose"-node (in case you want to look it // up in the help) MFnDependencyNode bindPoseNode(bindPosePlug.node()); // and as such, has the "xformMatrix"-attribute. MObject xformMatrixAttribute = bindPoseNode.attribute("xformMatrix"); MPlug localTransformPlug(bindPosePlug.node(), xformMatrixAttribute); // xformMatrix is an array. to get our localmatrix we need to select // the same index, as our bindPosePlug (logicalIndex()). localTransformPlug.selectAncestorLogicalIndex( bindPosePlug.logicalIndex(), xformMatrixAttribute); MObject localMatrixObject; localTransformPlug.getValue(localMatrixObject); // extract the matrix out of the object. return MFnMatrixData(localMatrixObject).matrix(); }
void MayaTransformWriter::pushTransformStack(const MFnIkJoint & iJoint, bool iForceStatic) { // check joints that are driven by Maya FBIK // Maya FBIK has no connection to joints' TRS plugs // but TRS of joints are driven by FBIK, they are not static // Maya 2012's new HumanIK has connections to joints. // FBIK is a special case. bool forceAnimated = false; MStatus status = MS::kSuccess; if (iJoint.hikJointName(&status).length() > 0 && status) { forceAnimated = true; } // inspect the translate addTranslate(iJoint, "translate", "translateX", "translateY", "translateZ", Alembic::AbcGeom::kTranslateHint, false, iForceStatic, forceAnimated, mSample, mAnimChanList); // inspect the inverseParent scale // [IS] is ignored when Segment Scale Compensate is false MPlug scaleCompensatePlug = iJoint.findPlug("segmentScaleCompensate"); if (scaleCompensatePlug.asBool()) { addScale(iJoint, "inverseScale", "inverseScaleX", "inverseScaleY", "inverseScaleZ", true, iForceStatic, forceAnimated, mSample, mAnimChanList); } MTransformationMatrix::RotationOrder eJointOrientOrder, eRotOrder, eRotateAxisOrder; double vals[3]; // for reordering rotate names MString rotateNames[3]; unsigned int rotOrder[3]; // now look at the joint orientation rotateNames[0] = "jointOrientX"; rotateNames[1] = "jointOrientY"; rotateNames[2] = "jointOrientZ"; iJoint.getOrientation(vals, eJointOrientOrder); if (util::getRotOrder(eJointOrientOrder, rotOrder[0], rotOrder[1], rotOrder[2])) { addRotate(iJoint, "jointOrient", rotateNames, rotOrder, Alembic::AbcGeom::kRotateHint, iForceStatic, true, mSample, mAnimChanList, mJointOrientOpIndex); } rotateNames[0] = "rotateX"; rotateNames[1] = "rotateY"; rotateNames[2] = "rotateZ"; // if this returns false then the rotation order was kInvalid or kLast eRotOrder = iJoint.rotationOrder(); if (util::getRotOrder(eRotOrder, rotOrder[0], rotOrder[1], rotOrder[2])) { addRotate(iJoint, "rotate", rotateNames, rotOrder, Alembic::AbcGeom::kRotateHint, iForceStatic, true, mSample, mAnimChanList, mRotateOpIndex); } // now look at the rotation orientation, aka rotate axis rotateNames[0] = "rotateAxisX"; rotateNames[1] = "rotateAxisY"; rotateNames[2] = "rotateAxisZ"; iJoint.getScaleOrientation(vals, eRotateAxisOrder); if (util::getRotOrder(eRotateAxisOrder, rotOrder[0], rotOrder[1], rotOrder[2])) { addRotate(iJoint, "rotateAxis", rotateNames, rotOrder, Alembic::AbcGeom::kRotateOrientationHint, iForceStatic, true, mSample, mAnimChanList, mRotateAxisOpIndex); } // inspect the scale addScale(iJoint, "scale", "scaleX", "scaleY", "scaleZ", false, iForceStatic, forceAnimated, mSample, mAnimChanList); // remember current rotation if (mFilterEulerRotations) { double xx(0), yy(0), zz(0); // there are 2 rotation order enum definitions: // MEulerRotation::RotationOrder = MTransformationMatrix::RotationOrder-1 if (getSampledRotation( mSample, mJointOrientOpIndex, xx, yy, zz )) { mPrevJointOrientSolution.setValue(xx, yy, zz, (MEulerRotation::RotationOrder)(eJointOrientOrder-1)); } if (getSampledRotation( mSample, mRotateOpIndex, xx, yy, zz )) { mPrevRotateSolution.setValue(xx, yy, zz, (MEulerRotation::RotationOrder)(eRotOrder-1)); } if (getSampledRotation( mSample, mRotateAxisOpIndex, xx, yy, zz )) { mPrevRotateAxisSolution.setValue(xx, yy, zz, (MEulerRotation::RotationOrder)(eRotateAxisOrder-1)); } } }