Getting Triangle UVs
[edit]
Problem
You want to get the UV values for mesh triangles.
[edit]
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("--------------------------------");
}
[edit]
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 2556 times.

