#include "skeleton.h" namespace OgreMayaExporter { // Constructor Skeleton::Skeleton() { m_joints.clear(); m_animations.clear(); } // Destructor Skeleton::~Skeleton() { clear(); } // Clear skeleton data void Skeleton::clear() { m_joints.clear(); m_animations.clear(); } // Load skeleton data from given skin cluster MStatus Skeleton::load(MFnSkinCluster* pSkinCluster,ParamList& params) { MStatus stat; //update skin cluster pointer if (!pSkinCluster) { std::cout << "Could not load skeleton data, no skin cluster specified\n"; return MS::kFailure; } //retrieve and load joints from the skin cluster MDagPath jointDag,rootDag; MDagPathArray influenceDags; int numInfluenceObjs = pSkinCluster->influenceObjects(influenceDags,&stat); std::cout << "num influence objects: " << numInfluenceObjs << "\n"; for (int i=0; i0) { jointDag.pop(); if (jointDag.hasFn(MFn::kJoint) && jointDag.length()>0) rootDag = jointDag; } //check if skeleton has already been loaded bool skip = false; for (int j=0; jname.asChar() << ")\n"; else std::cout << "\n"; // Get parent index int idx=-1; if (parent) { for (i=0; iname) idx=i; } } // Get joint matrix MMatrix bindMatrix = jointDag.inclusiveMatrix(); // Calculate scaling factor inherited by parent double scale[3]; if (parent) { MTransformationMatrix M(parent->worldMatrix); M.getScale(scale,MSpace::kWorld); } else { scale[0] = 1; scale[1] = 1; scale[2] = 1; } // Calculate Local Matrix MMatrix localMatrix; if (parent) localMatrix = bindMatrix * parent->worldMatrix.inverse(); else { // root node of skeleton if (params.exportWorldCoords) localMatrix = bindMatrix; else localMatrix = bindMatrix * jointDag.exclusiveMatrix().inverse(); } // Calculate rotation data double qx,qy,qz,qw; ((MTransformationMatrix)localMatrix).getRotationQuaternion(qx,qy,qz,qw); MQuaternion rotation(qx,qy,qz,qw); MVector axis; double theta; rotation.getAxisAngle(axis,theta); axis.normalize(); if (axis.length() < 0.5) { axis.x = 0; axis.y = 1; axis.z = 0; theta = 0; } // Set joint info newJoint.name = jointFn.partialPathName(); newJoint.id = m_joints.size(); newJoint.parentIndex = idx; newJoint.worldMatrix = bindMatrix; newJoint.localMatrix = localMatrix; newJoint.posx = localMatrix(3,0) * scale[0]; newJoint.posy = localMatrix(3,1) * scale[1]; newJoint.posz = localMatrix(3,2) * scale[2]; newJoint.angle = theta; newJoint.axisx = axis.x; newJoint.axisy = axis.y; newJoint.axisz = axis.z; newJoint.jointDag = jointDag; m_joints.push_back(newJoint); // Get pointer to newly created joint parentJoint = &newJoint; } // Load children joints for (i=0; i times; // if skeleton has no joint we can't load the clip if (m_joints.size() < 0) return MS::kFailure; // display clip name std::cout << "clip \"" << clipName.asChar() << "\"\n"; // calculate times from clip sample rate times.clear(); for (double t=start; t 0) length = times[times.size()-1] - times[0]; // check if clip length is >0 if (length <= 0) { std::cout << "the clip has 0 length, we skip it\n"; return MS::kFailure; } // create the animation animation a; a.name = clipName.asChar(); a.tracks.clear(); a.length = length; m_animations.push_back(a); int animIdx = m_animations.size() - 1; // create a track for current clip for all joints std::vector animTracks; for (i=0; i= 0) { //calculate inherited scale factor ((MTransformationMatrix)j.jointDag.exclusiveMatrix()).getScale(scale,MSpace::kWorld); //calculate relative matrix matrix = j.jointDag.inclusiveMatrix() * j.jointDag.exclusiveMatrixInverse(); } else { // root joint if (params.exportWorldCoords) matrix = j.jointDag.inclusiveMatrix(); else matrix = j.jointDag.inclusiveMatrix() * j.jointDag.exclusiveMatrixInverse(); } //calculate position of joint at given time position.x = matrix.asMatrix()(3,0) * scale[0]; position.y = matrix.asMatrix()(3,1) * scale[1]; position.z = matrix.asMatrix()(3,2) * scale[2]; //get relative transformation matrix matrix = matrix.asMatrix() * j.localMatrix.inverse(); //calculate rotation double qx,qy,qz,qw; ((MTransformationMatrix)matrix).getRotationQuaternion(qx,qy,qz,qw); MQuaternion rotation(qx,qy,qz,qw); double theta; MVector axis; rotation.getAxisAngle(axis,theta); axis.normalize(); if (axis.length() < 0.5) { axis.x = 0; axis.y = 1; axis.z = 0; theta = 0; } //create keyframe keyframe key; key.time = time; key.tx = position.x - j.posx; key.ty = position.y - j.posy; key.tz = position.z - j.posz; key.angle = theta; key.axis_x = axis.x; key.axis_y = axis.y; key.axis_z = axis.z; key.sx = 1; key.sy = 1; key.sz = 1; return key; } // Get joint list std::vector& Skeleton::getJoints() { return m_joints; } // Get animations std::vector& Skeleton::getAnimations() { return m_animations; } // Write skeleton data to Ogre XML file MStatus Skeleton::writeXML(ParamList ¶ms) { // Start skeleton description params.outSkeleton << "\n"; // Write bones list params.outSkeleton << "\t\n"; // For each joint write it's description for (int i=0; i\n"; params.outSkeleton << "\t\t\t\n"; params.outSkeleton << "\t\t\t\n"; params.outSkeleton << "\t\t\t\t\n"; params.outSkeleton << "\t\t\t\n"; params.outSkeleton << "\t\t\n"; } params.outSkeleton << "\t\n"; // Write bone hierarchy params.outSkeleton << "\t\n"; for (i=0; i=0) { params.outSkeleton << "\t\t\n"; } } params.outSkeleton << "\t\n"; // Write animations description if (params.exportAnims) { params.outSkeleton << "\t\n"; // For every animation for (i=0; i\n"; // Write tracks params.outSkeleton << "\t\t\t\n"; // Cycle through tracks for (int j=0; j\n"; // Write track keyframes params.outSkeleton << "\t\t\t\t\t\n"; for (int k=0; k\n"; // translation params.outSkeleton << "\t\t\t\t\t\t\t\n"; // rotation params.outSkeleton << "\t\t\t\t\t\t\t\n"; params.outSkeleton << "\t\t\t\t\t\t\t\t\n"; params.outSkeleton << "\t\t\t\t\t\t\t\n"; //scale params.outSkeleton << "\t\t\t\t\t\t\t\n"; params.outSkeleton << "\t\t\t\t\t\t\n"; } params.outSkeleton << "\t\t\t\t\t\n"; params.outSkeleton << "\t\t\t\t\n"; } // End tracks description params.outSkeleton << "\t\t\t\n"; // End animation description params.outSkeleton << "\t\t\n"; } params.outSkeleton << "\t\n"; } // End skeleton description params.outSkeleton << "\n"; return MS::kSuccess; } }; //end namespace