
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Hi,
I have a maya model attached in this post that I am trying to export.
I have my own rigged mesh representation.
In that, I export the
- bind pose world matrices for each joint (from the bindPose attribute on a joint node)
- the bind pose world vertex positions of the mesh
- the joint world matrices of each joint (using the inclusiveMatrix()) for each animation frame (all keyed on translation/rotation/scale)
- and the respective weights and joint indices for each vertex
I then perform skinning for frame i by doing:
skinned world vertex = (0, 0, 0)
skinned world vertex += (bind pose world vertex position) * (bindPose world matric inverse for joint k) * (world matrix for joint k on frame i) * (weight for joint k), for all joint k that influences that vertex
this approach works for some models but fails for the one I have (it just have one mesh with a hierarchy of joints)
I verify the approach by writing a command in maya that takes in a vertex idx and a frame idx and it outputs the world space bind pose points and world space skinned points by directly querying the maya mesh
this is the output from the command
// Selected mesh: |Ganfaul|GanfaulShape //
// GanfaulShape is a riggedMesh, skin cluster name: skinCluster1 //
// Checking mesh: GanfaulShape, vertexID: 4685, frameIdx: 3 //
// Bind Pose Local Space Point: -1.702918, 182.58876, 8.60685 //
// Bind Pose World Space Point: -1.702918, 182.58876, 8.60685 //
// Calculated Bind Pose World Space Point: -1.702918, 182.58876, 8.60685 //
// Num joint influence : 65 //
// Num weights for vertex: 511225 //
// Num joints for vertex : 65 //
// Valid joint idx: 59, name: Head, weight: 1, bind pose list name: Head //
// Frame Local Space Point: -3.06953, 175.204819, 7.018704 //
// Frame World Space Point: -3.06953, 175.204819, 7.018704 //
// Calculated Frame World Space Point: 4.036224, 153.692543, 25.453149 //
here is the code for the command
MObject skinClusterObj; MObject skinnedMeshObj = skinnedMeshDag.node(); if (!MayaHelper::isMeshRigged(skinnedMeshObj, skinClusterObj)) { MayaLog::OutputInfo(" TestCmd, selected mesh is not rigged"); return; } MStatus stats = MS::kSuccess; MayaHelper::animControlGoToFirstFrame(); MayaHelper::setAllJointToBindPose(); MFnMesh meshFn(skinnedMeshDag); MayaLog::OutputInfo(MString(" Checking mesh: ") + meshFn.name() + MString(", vertexID: ") + vertexId + MString(", frameIdx: ") + frameIdx); MPoint bindPoseLocalSpacePoint; MPoint bindPoseWorldSpacePoint; stats = meshFn.getPoint(vertexId, bindPoseLocalSpacePoint, MSpace::kObject); if (stats != MS::kSuccess) { MayaLog::OutputError(" Error getting bind pose local space point"); return; } stats = meshFn.getPoint(vertexId, bindPoseWorldSpacePoint, MSpace::kWorld); if (stats != MS::kSuccess) { MayaLog::OutputError(" Error getting bind pose world space point"); return; } MDagPath skinnedMeshParentDag = skinnedMeshDag; skinnedMeshParentDag.pop(); const MPoint bindPoseWorldCalculated = bindPoseLocalSpacePoint * skinnedMeshParentDag.inclusiveMatrix(); MayaHelper::printMPoint(MString(" Bind Pose Local Space Point: "), bindPoseLocalSpacePoint); MayaHelper::printMPoint(MString(" Bind Pose World Space Point: "), bindPoseWorldSpacePoint); MayaHelper::printMPoint(MString(" Calculated Bind Pose World Space Point: "), bindPoseWorldCalculated); MFnSkinCluster skinClusterFn(skinClusterObj); MDagPathArray jointDags; skinClusterFn.influenceObjects(jointDags); const unsigned int numJoints = jointDags.length(); // get bind pose world transforms struct JointBindPoseInfo { std::string jointName; MTransformationMatrix bindPoseWorldTransMat; JointBindPoseInfo() : jointName(""), bindPoseWorldTransMat(MTransformationMatrix::identity), {} }; std::vector<JointBindPoseInfo> jointsBindPoseWorld(numJoints); for (unsigned int i = 0; i < numJoints; ++i) { const MString jointName = jointDags[i].partialPathName(); MFnIkJoint jointFn(jointDags[i]); // get the world bind pose matrix for this bone // and store it in the bone desc MPlug bindPosePlug = jointFn.findPlug(c_jointNodeBindPoseAttrName); const MFnMatrixData bindPoseMatrixDataFn(bindPosePlug.asMObject()); // export bind pose world const MMatrix bindPoseMatWorld = bindPoseMatrixDataFn.matrix(); jointsBindPoseWorld[i].jointName = jointName.asChar(); jointsBindPoseWorld[i].bindPoseWorldTransMat = bindPoseMatWorld; MString transformName = jointName + MString("_bindPoseWorld"); } MayaHelper::animControlGoToFrame(frameIdx); MPoint frameWorldCalculated(0, 0, 0); MPoint frameLocalSpacePoint; MPoint frameWorldSpacePoint; stats = meshFn.getPoint(vertexId, frameLocalSpacePoint, MSpace::kObject); if (stats != MS::kSuccess) { MayaLog::OutputError(" Error getting frame local space point"); return; } stats = meshFn.getPoint(vertexId, frameWorldSpacePoint, MSpace::kWorld); if (stats != MS::kSuccess) { MayaLog::OutputError(" Error getting frame world space point"); return; } MDoubleArray weights; { MIntArray elementArray; elementArray.append(vertexId); MFnSingleIndexedComponent vertices; vertices.addElements(elementArray); MObject vertComponents = vertices.create(MFn::kMeshVertComponent); // numJointInfluences will always be number of bones in the skeleton even if they have weight of 0 // so weights will be numVerts * numJointInfluences big // however, joints not part of influence list are not counted unsigned int numJointInfluences = 0; skinClusterFn.getWeights(skinnedMeshDag, vertComponents, weights, numJointInfluences); const unsigned int numWeights = weights.length(); MayaLog::OutputInfo(MString(" Num joint influence : ") + numJointInfluences); MayaLog::OutputInfo(MString(" Num weights for vertex: ") + numWeights); MayaLog::OutputInfo(MString(" Num joints for vertex : ") + numJoints); std::vector<double> vertWeights(numJointInfluences, 0.0); for (unsigned int j = 0; j < numJointInfluences; ++j) { const double& weight = weights[vertexId * numJointInfluences + j]; vertWeights[j] = weight; } struct JointWeightInfo { MString jointName; MDagPath jointDag; double weight; JointWeightInfo() : jointName(""), jointDag(), weight(0.0) {} }; std::vector<JointWeightInfo> validJointAndWeights; for (unsigned int i = 0; i < numJointInfluences; ++i) { if (vertWeights[i] > 0.0) { JointWeightInfo weightInfo; weightInfo.jointName = jointDags[i].partialPathName(); weightInfo.jointDag = jointDags[i]; weightInfo.weight = vertWeights[i]; validJointAndWeights.emplace_back(weightInfo); MayaLog::OutputInfo(MString(" Valid joint idx: ") + i + MString(", name: ") + jointDags[i].partialPathName() + MString(", weight: ") + vertWeights[i] + MString(", bind pose list name: ") + jointsBindPoseWorld[i].jointName.c_str()); frameWorldCalculated += vertWeights[i] * (bindPoseWorldCalculated * jointsBindPoseWorld[i].bindPoseWorldTransMat.asMatrixInverse() * jointDags[i].inclusiveMatrix()); } } } MayaHelper::printMPoint(MString(" Frame Local Space Point: "), frameLocalSpacePoint); MayaHelper::printMPoint(MString(" Frame World Space Point: "), frameWorldSpacePoint); MayaHelper::printMPoint(MString(" Calculated Frame World Space Point: "), frameWorldCalculated); MayaHelper::animControlGoToFirstFrame(); MayaHelper::setAllJointToBindPose();
Is there any transform that I could have possibly not gotten from Maya to perform the skinning? It works well for most rigged meshs I created myself but for this model it doesn't. I would appreciate any help on this thanks!
Solved! Go to Solution.