MEL How-To #55 | ||
| ||
How can a get a list of all vertex or edge components from a polymesh in proper counter-clockwise or "render" order?The image at right depicts a selected polymesh face component. If we were to query this face using the API we would learn that Maya constructs this face in the vertex order: 295, 12, 14, 296. From this, logic will yield an "edge construction order" of: 582, 19, 584, 585. Deriving Vertex Order From A Face polyInfo The "polyInfo" command, when specified with its ` string $ftv[] = `polyInfo -faceToVertex m26_section.f[278]`; // Result: FACE 278: 295 12 14 296 // To extract the values in order to use them, use the string $tokens[]; tokenize $ftv[0] " :\n\r" $tokens; // Result: 6 // int $vertexOrder[]; clear $vertexOrder; int $t; for ( $t = 2; $t < `size $tokens`; $t++ ) { $vertexOrder[`size $vertexOrder`] = $tokens[$t]; }; print $vertexOrder; // Prints: 295 12 14 296 // polyListComponentConversion You can use the Joey Ponthieux (Video Applications Group, NASA Langley Research Center) struck upon using // This face ls -sl; // Result: m26_section.f[278] // // Use polyListComponentConversion to get .vtxFace components string $vtxFace[] = `polyListComponentConversion -fromFace -toVertexFace m26_section.f[278]`; // Result: m26_section.vtxFace[295][278] m26_section.vtxFace[12][278] m26_section.vtxFace[14][278] m26_section.vtxFace[296][278] // You can see the pattern in the order emerging. Now we just need to get this
represented in a more direct form. Use the // An array to store our result string $vertexOrder[]; for ( $vf in $vtxFace ) { // Get vertex for this vtxFace string $vertex[] = `polyListComponentConversion -fromVertexFace -toVertex $vf`; // And append to our result $vertexOrder[ size($vertexOrder) ] = $vertex[0]; } print $vertexOrder; // Result: m26_section.vtx[295] m26_section.vtx[12] m26_section.vtx[14] m26_section.vtx[296] // Expanding Results In "Range" Form The ls -sl; // Result: m26_section.f[6] // string $vtxFace[] = `polyListComponentConversion -fromFace -toVertexFace m26_section.f[6]`; // Result: m26_section.vtxFace[14][6] m26_section.vtxFace[13][6] m26_section.vtxFace[15:16][6] // Therefore, it's likely best to throw a // Use filterExpand to individualize each .vtxFace component in $vtxFace $vtxFace = `filterExpand -sm 70 -expand true $vtxFace`; // Result: m26_section.vtxFace[14][6] m26_section.vtxFace[13][6] m26_section.vtxFace[15][6] m26_section.vtxFace[16][6] // for ( $vf in $vtxFace ) { // Get vertex for this vtxFace string $vertex[] = `polyListComponentConversion -fromVertexFace -toVertex $vf`; // And append to our result $vertexOrder[ size($vertexOrder) ] = $vertex[0]; } print $vertexOrder; // Result: m26_section.vtx[14] m26_section.vtx[13] m26_section.vtx[15] m26_section.vtx[16] // Deriving Edge Order From A Face polyInfo The "polyInfo" command, when specified with its ` string $fte[] = `polyInfo -faceToEdge m26_section.f[278]`; // Result: FACE 278: 582 19 584 585 // To extract the values in order to use them, use the string $tokens[]; tokenize $fte[0] " :\n\r" $tokens; // Result: 6 // int $edgeOrder[]; clear $edgeOrder; int $t; for ( $t = 2; $t < `size $tokens`; $t++ ) { $edgeOrder[`size $edgeOrder`] = $tokens[$t]; }; print $edgeOrder; // Prints: 582 19 584 585 // polyListComponentConversion Using the $vtxFace array obtained in the above example, the edge construction order may be
obtained from the // An array to store our result string $edgeOrder[]; for ( $vf in $vtxFace ) { // Get edge for this vtxFace string $edge[] = `polyListComponentConversion -fromVertexFace -toEdge $vf`; // And append to our result $edgeOrder[ size($edgeOrder) ] = $edge[0]; } print $edgeOrder; // Result: m26_section.e[582] m26_section.e[19] m26_section.e[584] m26_section.e[585] // Note: Joey Ponthieux explains that this conversion to edge components appears
to only be reliable using Maya v3.0. In Maya 2.5 the returned edge does not necessarily correspond
to the same construction order of the input vertex. In this case it is necessary to
specify successive vertices and use the ‘ // Modified loop to accomodate Maya v2.5 // $vertexOrder derived in method described above for ( $v = 0; $v < size($vertexOrder); $v++ ) { int $nextVtx = ( $v < ( size($vertexOrder) - 1 ) ? $v + 1 : 0 ); // Use two successive vertices to derive internal edge string $edge[] = `polyListComponentConversion -fromVertex -toEdge -internal $vertexOrder[$v] $vertexOrder[$nextVtx]`; $edgeOrder[ size($edgeOrder) ] = $edge[0]; } print $edgeOrder; // Result: m26_section.e[582] m26_section.e[19] m26_section.e[584] m26_section.e[585] // Deriving Vertex Order From An Edge The "vertex order" implied here is that which corresponds to the winding order for the face. That is, such that the indices for the vertices are ordered as required to reconstruct the face in a manner preserving its face normal. It is possible (and likely) that an edge will be shared between two adjacent faces. Even though both faces are constructed in counter-clockwise order, their adjacent nature means that the vertex ordering for a shared edge is dependent upon for which face you are describing it. Given an edge shared by face 'A' and face 'B', the vertex order of the edge on face 'A' is exactly opposite to the vertex order of the edge on face 'B'. Therefore, for meaningful results, it is necessary to specify both an edge and a face to retrieve the vertex order for the edge. Again referring to geometry at right, the winding order for the edges is 582, 19, 584, 585. Specifying their vertex indices in similar fashion yields an ordering, per edge, of: { 295,12 }, { 12,14 }, { 14,296 }, { 296,295 }. Using a combination of the techniques described above it is a short stone's throw to expand the functionality of this process to derive the vertex order from an edge. The steps are as follows:
polyInfo Left as an exercise for the reader. Ain't I a stinker? polyListComponentConversion The following MEL procedure takes as arguments an edge component and related face component, and returns a string array containing the ordered vertex pair for the edge. global proc string[] edgeVertexOrder( string $inputEdge, string $inputFace ) { string $edgeVertexOrder[]; string $vertexOrder[]; // Note: polyListComponentConversion will return the components relative // to the TRANSFORM node. You may want to add an assertion/conversion // for the input arguments so they are relative to a transform. // If the input arguments are shape-relative then this procedure will FAIL. // Get vertex order of face string $vtxFace[] = `polyListComponentConversion -fromFace -toVertexFace $inputFace`; // Use filterExpand to individualize each .vtxFace component in $vtxFace $vtxFace = `filterExpand -sm 70 -expand true $vtxFace`; for ( $vf in $vtxFace ) { // Get vertex for this vtxFace string $vertex[] = `polyListComponentConversion -fromVertexFace -toVertex $vf`; // And append to our result $vertexOrder[ size($vertexOrder) ] = $vertex[0]; } // Now, check each vertex pair to see if it matches the specified edge for ( $v = 0; $v < size($vertexOrder); $v++ ) { int $nextVtx = ( $v < ( size($vertexOrder) - 1 ) ? $v + 1 : 0 ); // Use two successive vertices to derive internal edge string $edge[] = `polyListComponentConversion -fromVertex -toEdge -internal $vertexOrder[$v] $vertexOrder[$nextVtx]`; // Does this match? if ( $edge[0] == $inputEdge ) { $edgeVertexOrder[0] = $vertexOrder[$v]; $edgeVertexOrder[1] = $vertexOrder[$nextVtx]; // As soon as a match is found we can stop looking. break; } } // Warn if $inputEdge not found in $inputFace if ( size( $edgeVertexOrder ) == 0 ) warning ( $inputEdge + " is not part of " + $inputFace ); return $edgeVertexOrder; } An example run: edgeVertexOrder m26_section.e[582] m26_section.f[278]; // Result: m26_section.vtx[295] m26_section.vtx[12] // // This demonstrates that the adjacent face (.f[277]) evaluates its // vertex order in the opposite direction, as described in the text. // edgeVertexOrder m26_section.e[582] m26_section.f[277]; // Result: m26_section.vtx[12] m26_section.vtx[295] // edgeVertexOrder m26_section.e[584] m26_section.f[277]; // Warning: m26_section.e[584] is not part of m26_section.f[277] // Acknowledgements
Related How-To's18 Sep 2004 | ||
Copyright ©2005 by Bryan Ewert, maya@ewertb.com Maya is a Registered Trademark of Alias |