Maya API How-To #09 | ||
| ||
How do I extract animated polymesh vertex coordinates?Preamble This How-To is the direct result of my being stonewalled for three days while trying to determine how to do this (seemingly) simple feat without causing Maya to crash and burn at every turn. I express sincere gratitude towards Justin Miller (DreamWorks) and Mark McGrevy (SONY) for their helpful advice. Justin suggested the MDGContext technique, and Mark explained for me why my original code wasn't working. Thanks also to William McCullough for providing the Highend3D Maya forums, without which I'd still be stuck on this problem. Method #1: Advancing Time This technique is straight-forward and intuitive. Start at the first frame of the animation (acquired from MAnimControl::minTime()) and march through each consecutive frame until you reach the end of the animtion (MAnimControl::maxTime()). At each time stop, grab the coordinates for the vertices (using MFnMesh::getPoints()). There seems to be a consensus amongst developers for using MGlobal::viewFrame() over MAnimControl::setCurrentTime(). The former forces a refresh of Maya's interactive view whereas the latter simply flags it as "dirty." The opinion is that ::viewFrame() is the more reliable, and who am I to argue with the experts? The following class method can be used to query vertex coordinates at a given frame (or "time" if you prefer): // ************************************************************************************************ // Function: GetPointsAtTime // // Description: Sets Maya to the specified Time and gets the object-space vertex coordinates // from the specified DAG at the that Time. // // Input: const MDagPath& dagPath: The DAG path for the mesh object. // const MTime& mayaTime: The Time at which to query the vertex coordinates. // MPointArray& points: Storage for the array of vertex coordinates. // // Output: (MStatus): MS::kSuccess if it worked; else MS::kFailure. // ************************************************************************************************ MStatus myPlugIn::GetPointsAtTime( const MDagPath& dagPath, const MTime& mayaTime, MPointArray& points ) { MStatus status = MS::kSuccess; points.clear(); MFnMesh fnMesh; // Move Maya to current frame MGlobal::viewFrame( mayaTime ); // You MUST reinitialize the function set after changing time! fnMesh.setObject( dagPath ); // Get vertices at this time status = fnMesh.getPoints( points ); return status; } Below is an example use of the GetPointsAtTime function: MStatus myPlugIn::doIt( const MArgList& args ) { MStatus status = MS::kSuccess; MDagPath dagPath; // .. determing dagPath from current selection, or whatever .. // MPointArray points; MTime currentTime, maxTime; // Get start- and end-frame from Maya currentTime = MAnimControl::minTime(); maxTime = MAnimControl::maxTime(); // Iterate through time while ( currentTime <= maxTime ) { // Get vertices at this time status = GetPointsAtTime( dagPath, currentTime, points ); // .. do something with the points here .. // // Advance by one frame currentTime++; } return status; } Method #2: Using Time in Context There is one important consideration for using the "Advancing Time" technique for extracting vertex animation: Performance. Maya's API documentation warns that ::viewFrame() is slow. This is understandable as it forces a refresh for the entire dependency graph, even for the nodes that have no influence on the mesh object you are probing. The recommended alternative is to "create an instance of the MDGContext class initialized to the time you are interested in" and "pass it to the getValue method of the MPlug class." So how can you get vertex coordinates by querying an attribute? Every mesh has an attribute with this exact information: ‘ [kBase, kMesh, kData, kMeshData, kGeometryData] Thus, conveniently, you can use the MFnMesh function set and treat the plug like it was the mesh itself. The following class method shows how to use MPlug and MDGContext to query vertex coordinates at a given time: // ************************************************************************************************ // Function: GetPointsAtTimeContext // // Description: Gets the object-space vertex coordinates from the specified DAG at // the specified Time. // // Input: const MDagPath& dagPath: The DAG path for the mesh object. // const MTime& mayaTime: The Time at which to query the vertex coordinates. // MPointArray& points: Storage for the array of vertex coordinates. // // Output: (MStatus): MS::kSuccess if it worked; else MS::kFailure. // ************************************************************************************************ MStatus myPlugIn::GetPointsAtTimeContext( const MDagPath& dagPath, const MTime& mayaTime, MPointArray& points ) { MStatus status = MS::kSuccess; points.clear(); MFnDependencyNode fnDependNode( dagPath.node(), &status ); MPlug plugMesh; MObject meshData; // Get the .outMesh plug for this mesh plugMesh = fnDependNode.findPlug( MString( "outMesh" ), &status ); // Get its value at the specified Time. status = plugMesh.getValue( meshData, MDGContext( mayaTime ) ); // Use its MFnMesh function set MFnMesh fnMesh( meshData, &status ); // And query the point coordinates status = fnMesh.getPoints( points ); return status; } Related How-To's30 March 2003 | ||
Copyright ©2005 by Bryan Ewert, maya@ewertb.com Maya is a Registered Trademark of Alias |