MEL How-To #05 | ||
| ||
How do I get the normal vector for a polygon face or vertex?Querying Per-Vertex Per-Face Normals There is a " polyNormalPerVertex -q -xyz; // Result: 0 1 0 0 0 1 -1 0 0 // These results indicate that the vertex is associated with three faces. The normals are: { 0.0, 1.0, 0.0 }, { 0.0, 0.0, 1.0 }, { -1.0, 0.0, 0.0 } You could average these three to obtain the shared vertex normal, if desired. Unfortunately, this doesn't tell you which normal correlates to which associated face. To really know you must work with .vtxFace components. // Convert a .vtx component to .vtxFace components. string $plcc[] = `polyListComponentConversion -fv -tvf pCube1.vtx[2]`; // Expand the list to avoid Maya's component compression $plcc = `filterExpand -sm 70 -ex true $plcc`; for ( $vtxFace in $plcc ) { // Get the per-vertex per-face normal for this component float $normal[3] = `polyNormalPerVertex -q -xyz $vtxFace`; print( $vtxFace + ": { " + $normal[0] + ", " + $normal[1] + ", " + $normal[2] + " }\n" ); } Example run: pCube1.vtxFace[2][0]: { 0, 0, 1 } pCube1.vtxFace[2][1]: { 0, 1, 0 } pCube1.vtxFace[2][5]: { -1, 0, 0 } Using 'polyInfo' The polyInfo command has a '-faceNormal' flag which can be used to obtain the vector for a face. Two quirks with this method:
We can work around both of these with a little helper procedure. polyInfo -fn pSphere1.f[7]; // Result: FACE_NORMAL 7: -0.090404 -0.135299 0.017982 // polyInfo -fn pCube1.f[0]; // Result: FACE_NORMAL 0: 0.000000 0.000000 2.000000 // Here's our helper script: proc vector translatePolyInfoNormal( string $pin ) { vector $normal; float $x; float $y; float $z; string $tokens[]; int $numTokens = `tokenize $pin " " $tokens`; // Make sure we're looking at polyInfo data: if ( ( $numTokens > 3 ) && ( $tokens[0] == "FACE_NORMAL" ) ) { // Maya performs data-type conversion here. $x = ($tokens[$numTokens-3]); $y = ($tokens[$numTokens-2]); $z = ($tokens[$numTokens-1]); $normal = << $x, $y, $z >>; // Normalize it. $normal = `unit $normal`; } // Return it. return $normal; } Now let's put it to use: string $sphereInfo[] = `polyInfo -fn pSphere1.f[7]`; // Result: FACE_NORMAL 7: -0.090404 -0.135299 0.017982 vector $sphereNormal = translatePolyInfoNormal( $sphereInfo[0] ); // Result: <<-0.552209, -0.826438, 0.109838>> // string $cubeInfo[] = `polyInfo -fn pCube1.f[7]`; // Result: FACE_NORMAL 5: -2.000000 0.000000 0.000000 vector $cubeNormal = translatePolyInfoNormal( $cubeInfo[0] ); // Result: <<-1, 0, 0>> // Using The Cross Product // Pick a face, any face string $node = "polySurface1"; int $face = 0; // Get vertex list for face int $vertices[] = facetVertices( $node + ".f[" + $face + "]" ); // Get coordinates for each of the three vertices vector $vector[3]; for ( $p = 0; $p < 3; $p++ ) { float $coord[3]; $command = "xform -q -ws -t " + $node + ".vtx[" + $vertices[$p] + "]"; $coord = `eval $command`; $vector[$p] = << $coord[0], $coord[1], $coord[2] >>; } vector $v0, $v1, $v2; // Reassign to non-array variables to allow access // to vector components (e.g. vector.x) $v0 = $vector[0]; $v1 = $vector[1]; $v2 = $vector[2]; // Get two vectors for surface definition, from the 3 verts. vector $def[2]; $def[0] = << $v0.x - $v2.x, $v0.y - $v2.y, $v0.z - $v2.z >>; $def[1] = << $v1.x - $v2.x, $v1.y - $v2.y, $v1.z - $v2.z >>; // Get normal vector $normal; // The cross product provides the normal for the surface defined from these two vectors $normal = `cross $def[0] $def[1]`; This script only considers the first three vertices for the given face. If your face is planar, this is fine. If your face is comprised of more than three vertices and it is not planar then the results will be inaccurate. Be aware that the direction of the surface normal is dependent on the direction of your edge vectors. To ensure accurate results you'll want to make sure that the vertices are queried in render order. Querying The 'mesh' Node On a whim, I tried to see if it was possible to query one of the ' getAttr pSphere1.vn[0].vfnl[0].fnxy; // Result: 100000002004087730000 100000002004087730000 100000002004087730000 // Given the results, I think not. References for Cross Product Acknowledgement Joseph A. Hansen, Tools Manager, Beyond Games Related How-To's22 February 2003 | ||
Copyright ©2005 by Bryan Ewert, maya@ewertb.com Maya is a Registered Trademark of Alias |