The Poly API consists of five main classes:
See MItMeshPolygon.
See MItMeshEdge.
See MFnMesh.
The first four classes are iterators while the last class is a function set. The polygon iterators are primarily used to navigate or parse a mesh component by component and retrieve component specific information. The polygon function set, MFnMesh, is used to create, modify, and retrieve mesh specific data.
MItMeshPolygon is a polygonal face iterator. Initializing this class to a specific mesh object lets you iterate over all faces in a mesh, in order of face ids. Alternatively, the iterator can be restricted to the faces adjacent to a given component (for example, edge or vertex) by initializing the class to both a DAG path referring to the mesh and an MObject reference to certain components.
This iterator is useful for parsing a mesh as it can traverse the mesh more quickly—there are fewer faces than edges and vertices and less overlap in data retrieval. As a face iterator, MItMeshPolygon provides methods to retrieve face-specific data mostly comprised of:
MItMeshPolygon is ideal for cases where you would like to quickly search a mesh on a face-by-face basis or when you require face specific data from the mesh. To see how this class is used, refer to the splitUVCmd example. The following example also illustrates the use of the MItMeshPolygon class. In this sample code, MItMeshPolygon is used to traverse the mesh for a specific face and then retrieve the edges making up the face.
MStatus getFaceEdges( MObject mesh,
int faceId,
MIntArray faceEdges )
{
MStatus status;
// Reset the faceEdges array
//
faceEdges.clear();
// Initialize a face iterator and function set
//
MItMeshPolygon faceIter( mesh, &status );
MCheckStatus( status, “MItMeshPolygon constructor failed” );
MFnMesh meshFn( mesh, &status );
MCheckStatus( status, “MFnMesh constructor failed” );
// Check to make sure that the faceId passed in is valid
//
if( faceId >= meshFn.numPolygons() || faceId < 0 )
{
cerr << “Invalid faceId.\n”;
status = MS::kFailure;
}
else
{
// Now parse the mesh for the given face and
// return the edges
//
for( ; !faceIter.isDone(); faceIter.next() )
{
// If we find the matching face, retrieve the
// edge indices
//
if( faceIter.index() == faceId )
{
faceIter.getEdges( faceEdges );
break;
}
}
}
return status;
}
MItMeshEdge iterates over the mesh on an edge-by-edge basis and retrieves edge specific data. This edge iterator iterates over the edges in order of edge ids or it iterates over the edges adjacent to a passed in component. MltMeshEdge can retrieve the following types of data:
MItMeshEdge is best suited for an edge-by-edge traversal of the mesh and for fetching edge specific data. The following sample code illustrates the use of the edge iterator. This example traverses each edge in the mesh and collects their start vertices, storing them inside an array indexed by edge id.
MStatus getEdgeStartVertices( MObject mesh,
MPointArray& pointArray )
{
MStatus status;
// Clear the output array
//
pointArray.clear();
// Initialize our iterator
//
MItMeshEdge edgeIter( mesh, &status );
MCheckStatus( status, “MItMeshEdge constructor failed” );
// Now parse the mesh
//
for( ; !edgeIter.isDone(); edgeIter.next() )
{
// Retrieve the start vertex of each edge and append it to
// our point array. Use the default object coordinate
// system for our space
//
pointArray.append( edgeIter.point(0, MSpace::kObject) );
}
return status;
}
MItMeshVertex and MItMeshFaceVertex
MItMeshVertex iterates over the mesh on a vertex-by-vertex basis in order of vertex ids, retrieving vertex specific data. The vertex iterator is best suited for those two cases and can retrieve vertex specific data such as:
MItMeshFaceVertex iterates over the mesh on a face vertex-by-face vertex basis in order of face ids, retrieving face-vertex specific data. The face vertex iterator can retrieve data such as:
MFnMesh contains several methods for retrieving mesh specific data and modifying a mesh. You could use an iterator to find a particular component and use MFnMesh to perform an operation on that component. This is shown in the splitUVCmd example which searches the mesh for a given UV and uses MFnMesh to “split” the UVs.
Although there is some overlap between the methods provided by MFnMesh and the MItMesh* iterators, MFnMesh represents more of a global library of operations for the mesh, while the iterators remain centric around their respective components. The following sample code demonstrates some things you might use MFnMesh for. The example retrieves various data and modifies it. Note that this code cannot be compiled.
// The argument list contains a “...” to represent a “Fill in
// the data you would like here”
//
MStatus getRandomPolyData( MObject mesh, ... )
{
MStatus status;
// Initialize a function set to a polygonal mesh
//
MFnMesh meshFn( mesh, &status );
MCheckStatus( status, “MFnMesh constructor failed” );
// Retrieve topological information
//
int faceCount = meshFn.numPolygons();
int edgeCount = meshFn.numEdges();
int vertexCount = meshFn.numVertices();
int faceVertexCount = meshFn.polygonVertexCount();
int UVCount = meshFn.numUVs();
MPointArray vertexList;
meshFn.getPoints( vertexList );
MFloatArray UArray;
MFloatArray VArray;
meshFn.getUVs( UArray, VArray );
// Modify topological information
//
// Add a UV to the UV list – setUV will automatically grow
// the UV list, based on the given index
//
meshFn.setUV( numUVs, 0.0, 0.0 );
// Move vertex 0 to the origin of the world
//
MPoint origin( 0.0, 0.0. 0.0 );
meshFn.setPoint( 0, origin, MSpace::kWorld );
// Can also work with:
//
// - Vertex Colors
// - Blind data
// - etc.
//
}