Getting Triangle UVs


Problem

You want to get the UV values for mesh triangles.

Scripting Solution

From scripting, a good way to access triangle node UVs is by finding the cluster properties for UVSpace, iterating over the polygon faces, and then match up to the UVs to the triangle nodes.

// --------------------------------------------------------------------
// set up the scene... a simple sphere with two texture projections
NewScene(null, null);
CreatePrim("Sphere", "MeshSurface", null, null);
ApplyShader(null, "", null, "", siLetLocalMaterialsOverlap);
CreateProjection("sphere", siTxtSpherical, null, "TS_Spherical", "TP_Spherical", null, null, null);
CreateProjection("sphere", siTxtDefaultPlanarXY, null, "TS_XY", "TP_XY", null, null, null);

// --------------------------------------------------------------------
// Get the clusters into an array
var oUVArray = new Array();
var oSphere = Dictionary.GetObject("sphere");
var oSphereGeom = oSphere.ActivePrimitive.Geometry;

logmessage("Finding Clusters and Cluster Properties on " + oSphere.Name);
logmessage("--------------------------------");

for (var i=0; i < oSphere.ActivePrimitive.Geometry.Clusters.Count; i++)
{
	var oCluster = oSphere.ActivePrimitive.Geometry.Clusters(i);
	logmessage("Cluster: " + oCluster.Name);

	for (var j=0; j < oCluster.LocalProperties.Count; j++)
	{
		var oLocalProp = oCluster.LocalProperties(j);
		if (ClassName(oLocalProp) == "ClusterProperty")
		{
			logmessage("   " + oLocalProp.FullName + " (Type: " + oLocalProp.Type + ")");
			curUVs = oLocalProp.Elements.Array.toArray();
			
			var Polygons = oSphereGeom.Polygons;
			for(i = 0; i < Polygons.Count; i++)
			{
			   var Polygon = Polygons.Item(i);
			   var NbTriangles = Polygon.NbPoints-2;

			   var PolygonVertices = Polygon.Vertices;
			   var PolygonNodes = Polygon.Nodes;
			   var TriangleSubIndices = Polygon.TriangleSubIndexArray.toArray();

			   for(j = 0; j < NbTriangles; j++)
			   {
			       Application.LogMessage("SubTriangle " + j + " of Polygon " + i + " correspond to vertices (" + 
			          PolygonVertices.Item(TriangleSubIndices[j*3]).Index + ", " +
			          PolygonVertices.Item(TriangleSubIndices[j*3+1]).Index + ", " +
			          PolygonVertices.Item(TriangleSubIndices[j*3+2]).Index + ") and nodes (" +
			          PolygonNodes.Item(TriangleSubIndices[j*3]).Index + ", " +
			          PolygonNodes.Item(TriangleSubIndices[j*3+1]).Index + ", " +
			          PolygonNodes.Item(TriangleSubIndices[j*3+2]).Index + ").");
	          
			       var NodeIndex = PolygonNodes.Item(TriangleSubIndices[j*3]).Index;
				   Application.LogMessage("   Node(" + NodeIndex +
				      " has UVW values (" + curUVs[NodeIndex*3] + ", " + curUVs[NodeIndex*3 + 1] + ", " + curUVs[NodeIndex*3 + 2] + ")");
				   NodeIndex = PolygonNodes.Item(TriangleSubIndices[j*3+1]).Index
				   Application.LogMessage("   Node(" + NodeIndex +
				      " has UVW values (" + curUVs[NodeIndex*3] + ", " + curUVs[NodeIndex*3 + 1] + ", " + curUVs[NodeIndex*3 + 2] + ")");
				   NodeIndex = PolygonNodes.Item(TriangleSubIndices[j*3+2]).Index
				   Application.LogMessage("   Node(" + NodeIndex +
				      " has UVW values (" + curUVs[NodeIndex*3] + ", " + curUVs[NodeIndex*3 + 1] + ", " + curUVs[NodeIndex*3 + 2] + ")");
			   }
			}
		}
	}
	
	logmessage("--------------------------------");
}

CPP Solution

The best way to access triangle UVs from a Mesh in C++ is through the CGeometryAccessor class. You can retrieve all the UVs or a given set of UVs by their name. Then, index into the list using the triangle node indices. Below is a sample CPP function that can be put into a Custom Command or Custom Operator.

//=====================================================================
// PrintUVsFromMesh
// - GetUVs() can be replaced by GetUV(CString name) which will then
//   only return the named UV set.
//=====================================================================
bool PrintUVsFromMesh(const PolygonMesh & in_mesh)
{
    Application app;

    // gets a geometry accessor object from the new mesh
    CGeometryAccessor ga = in_mesh.GetGeometryAccessor( );

    // gets all UVs on the mesh
    CRefArray uvs = ga.GetUVs();

    // loop through the UVs for this object
    for (LONG j=0; j<uvs.GetCount(); j++)
    {
        // works with the first UV set on the geometry
        // UV values are stored as a flat list of float values grouped in
        // triplets (i.e. UVW), first triplet being the values at node 0, etc...
        ClusterProperty uvProp = uvs[j];
        CFloatArray uvValues;
        uvProp.GetValues( uvValues );
        app.LogMessage( L"Texture: " + uvProp.GetName() );

        // retrieve all node indices per triangle on the geometry
        // nodes are grouped in triplets, first triplet being the nodes for
        // triangle 0, etc...
        CLongArray triNodeIds;
        ga.GetTriangleNodeIndices( triNodeIds );

        // loops over triangles and log their UV values
        LONG triID = 0;
        for ( LONG i=0; i<triNodeIds.GetCount( ); i+=3 )
        {
            app.LogMessage( L"Triangle " + CString( triID++ ) );

            // loop over each triangle node, use the node id to index into the
            // UV value array
            for ( LONG k=0; k<3; k++ )
            {
                LONG nodeId = triNodeIds[ i+k ];

                // shift by 3 since the datum size for a UV value is 3 (i.e. UVW)
                LONG uvIdx = nodeId*3;
                float u = uvValues[ uvIdx + 0 ];
                float v = uvValues[ uvIdx + 1 ];
                float w = uvValues[ uvIdx + 2 ];

                CString strUVW;
                wchar_t strFloat[32];

                swprintf(strFloat, L"%f", u );
                strUVW += strFloat;
                strUVW += L" ";
                swprintf(strFloat, L"%f", v );
                strUVW += strFloat;
                strUVW += L" "; 
                swprintf(strFloat, L"%f", w );
                strUVW += strFloat;

                app.LogMessage( L"   Node " + CString( nodeId ) + L": " + strUVW );
            }
        }
    }

    return true;
}

This page was last modified 20:55, 2 Nov 2010.
This page has been accessed 4703 times.

© Copyright 2009 Autodesk Inc. All Rights Reserved. Privacy Policy | Legal Notices and Trademarks | Report Piracy