Mel Script - Polygonal Mesh Data [API]





A polygonal mesh surface in Maya is a node of type "mesh". This is usually parented under a transform. In the example above, pCube1 is the transform for the shape, pCubeShape1 is the actual mesh node which is connected to a shading group to give the surface it's material properties.




Creating a Mesh

Normally when you create a polygonal mesh, you are actually asking for a polygon primitive to be made. Creating a polygon primitive involves creating a poly creator node to generate some mesh data, which is then output into an actual mesh object.

This is the mechanism that gives us scene history. Since the poly creator nodes exist within the scene graph, editing their attributes cause different vertices to be generated and sent into the mesh node.

If for some reason you want to create a mesh shape other than the default Maya primitives, then you will problably want to make use of MFnMesh within the Maya API rather than doing it in mel.





			//  Script to generate polygonal primitives 
			// create a poly cone
			polyCone -sx 10 -sy 15 -sz 5 -r 1 -h 2;
			xform -t 10 0 0;
			// create a poly cube
			polyCube -sx 10 -sy 15 -sz 5 -h 1;
			xform -t 6 0 0;
			// create a poly cylinder
			polyCylinder -sx 10 -sy 15 -sz 5 -h 2;
			xform -t 2 0 0;
			// create a poly plane
			polyPlane -sx 10 -sy 15 -w 1 -h 1;
			xform -t -2 0 0;
			// create a poly sphere
			polySphere -r 1 -sx 20 -sy 20 -ax 0 1 0 -tx 1 -ch 1;
			xform -t -6 0 0;
			// poly torus
			polyTorus -sx 8 -sy 16 -r 2 -sr 1;
			xform -t -10 0 0;



Finding All Meshes in a Scene

Using the mel command ls we are able to list nodes of a specific type within the Maya scene.



		// get a list of all meshes in the scene
		$meshes = `ls -type "mesh"`;

		// loop through each mesh
		for( $mesh in $meshes )
			// print the name of the mesh
			print( $mesh + "\n" );



Accessing local Space Vertices

Polygonal Meshes within Maya contain a list of points, and a list of relative vertex tweaks. We can determine the number of vertices within the mesh by using polyEvaluate, and then it is simply just a case of accessing the elements within the vertices and points arrays of the mesh (pt and vt).

These vertices are often shared by a number of faces, the faces therefore store indices into the vertex array.



		proc getVertices( string $mesh )
			//	get the number of vertices used in the mesh
			int $vertexCount[] = `polyEvaluate -v $mesh`;
			//	print number of vertices
			print( "numVertices=" + $vertexCount[0] + "\n" );
			//	process each vertex
			for( $i=0;$i<$vertexCount[0];$i++)
				//	get vertex co-ord and any relative tweaks
				float $vert[]   = `getAttr ($mesh+".vt["+$i+"]")`;
				float $offset[] = `getAttr ($mesh+".pt["+$i+"]")`;
				//	final vert pos = vertex + offset, output it!
				$vert[0] += $offset[0];
				$vert[1] += $offset[1];
				$vert[2] += $offset[2];
				print( $vert[0] + " " + $vert[1] + " " + $vert[2] + "\n" );




Accessing Texturing Coordinates

Texture Coordinates are used to store the placement of textures on polygonal surfaces. Texture Coordinates have a range of 0,0 to 1,1 (though they can be repeated) and tells Maya which part of the texture to apply to any given polygon.

As with vertices, texture coordinates can also be shared by more than one polygonal face. The faces then store indices into the texture coordinate array. Normally there is NO correlation between the indices for vertices and those of the texture coords. ie, if a given point on a polygon uses vertex 0, it is not guarenteed that it will use texture coord 0.




		proc getTexturingCoords( string $mesh )
			//	get number of uvs on the mesh
			int $uvCount[] = `polyEvaluate -uv $mesh`;
			//	write the number of UV coords
			print( "numTexCoords=" + $uvCount[0] + "\n" );
			//	add each uv coord to the string also
			for( $i=0;$i<$uvCount[0];$i++)
				//	get the uv coord
				float $uvs[] = `getAttr ($mesh + ".uv[" +$i+"]")`;
				//	print it's value
				print( $uvs[0] + " " + $uvs[1] + "\n" );



Accessing Face Information

The face data for polygonal meshes is basically composed of indices into the meshes vertex and texture co-ordinate arrays. In the Maya API you can also access the shared normal arrays, I'm not sure if this is possible in mel (last time I looked - about version 4.0 - I couldn't find a way). Instead the vertex normals of the mesh are determined by selecting each vertex/face pair and calling polyNormalPerVertex.



		proc getFaceInfo( string $mesh )
			//	get number of faces on the mesh
			select -r $mesh;
			int $faceCount[] = `polyEvaluate -f`;
			print( "numFaces=" + $faceCount[0] );
			//	process each face to find some info about it
			for( $i=0;$i<$faceCount[0];$i++)
				int $vCount =0;
				select -r ( $mesh+".f["+$i+"]");
				//	find the vertex indices used by this face and split the returned string
				//	to make life easier ...
				string $vinds[] = `polyInfo -fv`;
				string $split[];
				tokenize $vinds[0] $split;
				//	add the face number and vertex count for this face to the string
				print( " numPoints=" + (`size($split)`-2) );
					//	select the vertex/face pair
					select -r ($mesh+".vtxFace["+$split[($j+2)]+"]["+$i+"]");
					//	use polyNormalPerVertex to get the vertex normal values....
					float $norm[] = `polyNormalPerVertex -q -xyz`;
					//	query the vertex/face relationship to see which uv
					//	it uses
					string $tinds[] = `polyListComponentConversion -fvf -tuv 
					//	split the string to get the [] at the end...
					string $buffer[];
					tokenize $tinds[0] "[]" $buffer;
					//	put all the info together
					print( "   " + $split[(2+$j)] + //	vertex index number
					        "  " + $buffer[1]     + //	the tex coord index number
					        "  " + $norm[0]       + //	the x component of the normal
					         " " + $norm[1]       + //	the y component of the normal
					         " " + $norm[2] +"\n" );//	the z component of the normal