Home > User Guide > Display and User Input > Faceting
Converting Code that Traverses Facets in an INDEXED_MESH into Code that Traverses Facets in a LINKED_MESH
The following examples illustrate reading facet data from an INDEXED_MESH, and taking advantage of a higher performance faceter class. The newer class LINKED_MESH is a super-set of data that is contained in the older class INDEXED_MESH. When api_facet_entity uses LINKED_MESH_MANAGER instead of INDEXED_MESH_MANAGER, it performs significantly faster but results in a slightly larger memory footprint. A base class, SEQUENTIAL_MESH, was created to provide a common access to both classes. These examples are not only for those who wish to convert data using the faster LINKED_MESH class, but also serves as examples for those unfamiliar with the LINKED_MESH and the INDEXED_MESH classes.
This section contains snippets of C++ code to illustrate how to traverse facets in an INDEXED_MESH. These snippets are designed to be very simple starting points for developing your own code - they are not complete, compiling and runtime programs.
INDEXED_MESH code converted to LINKED_MESH code Example -1
The following function is an example of one of the ways to traverse facets in an INDEXED_MESH. This shows how to traverse only the polygons.
Note: To see how to traverse the vertices first, then the polygons, see Linked Mesh Example - 2.
void writeINDEXED_MESH(ENTITY * inEntity, FILE* fp) { // Get the transform on the body, if any. SPAtransf xform; ENTITY * owner; api_get_owner( inEntity, owner ); if ( is_BODY( owner ) ) { BODY * body; body = (BODY *)owner; if ( body->transform() ) xform = body->transform()->transform(); } ENTITY_LIST faceList; api_get_faces( inEntity, faceList ); // Loop through each face and print facet data for ( int faceIndex = 0; faceIndex < faceList.count(); faceIndex++ ) { FACE * face = (FACE*)faceList[faceIndex]; // Find the attribute for facets attached to the face. This is the mesh. MESH * face_mesh = NULL; af_query( (ENTITY*)face, IDX_MESH_APP, IDX_MESH_ID, face_mesh ); INDEXED_MESH *mesh = (INDEXED_MESH*)face_mesh; if (mesh && mesh->get_type_of_mesh() != INDEXED_MESH_TYPE) mesh = 0; if ( mesh == NULL ) { printf( "No indexed mesh available for face\n" ); continue; } // Loop through each facet and print its data int polygonCount = mesh->get_num_polygon(); for ( int polygonIndex = 0; polygonIndex < polygonCount; polygonIndex++ ) { // Get the facet's data as a mesh_polygon mesh_polygon* poly = mesh->get_polygon( polygonIndex ); if ( !poly ) continue; int nodeCount = poly->num_vertex(); if ( nodeCount <= 0) continue; fprintf( fp, "Face %d. Polygon %d\n", faceIndex, polygonIndex ); // Loop through each node of this facet, printing its data for ( int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++ ) { // Get the node's data as a polygon_vertex and print it polygon_vertex* vert = poly->get_vertex( nodeIndex ); if ( vert ) { SPAposition pos = vert->get_position(); SPAunit_vector vec = vert->get_normal(); SPApar_pos uv = vert->get_uv(); pos *= xform; vec *= xform; fprintf( fp, "position=(%f %f %f) normal=(%f %f %f) uv=(%f %f)\n", pos.x(), pos.y(), pos.z(), vec.x(), vec.y(), vec.z(), uv.u, uv.v ); } } // End braces for Loop through each node of this polygon } // End braces for Loop through each polygon } // End braces for Loop through each face }The following example performs the same operation as the one above, but uses a SEQUENTIAL_MESH. This is the base class for both INDEXED_MESH and LINKED_MESH. Using a LINKED_MESH will improve faceting performance. The differences is the code used to call af_query and three extra lines of code to call get_seq_polygon.
void writeSEQUENTIAL_MESH_METHOD1 ( ENTITY * inEntity, FILE* fp ) { // Get the transform on the body, if any. SPAtransf xform; ENTITY * owner; api_get_owner( inEntity, owner ); if ( is_BODY( owner ) ) { BODY * body; body = (BODY *)owner; if ( body->transform() ) xform = body->transform()->transform(); } ENTITY_LIST faceList; api_get_faces( inEntity, faceList ); // Loop through each face and print facet data for (int faceIndex = 0; faceIndex < faceList.count(); faceIndex++) { FACE * face = (FACE*)faceList[faceIndex]; // Find the attribute for facets attached to the face. This is the mesh. MESH * face_mesh = NULL; af_query( (ENTITY*)face, IDX_MESH_APP, IDX_MESH_ID, face_mesh ); if ( face_mesh == NULL ) { printf( "No indexed mesh or linked mesh available for a face\n" ); continue; } SEQUENTIAL_MESH *mesh = (SEQUENTIAL_MESH*)face_mesh; // Loop through each facet and print its data int polygonCount = mesh->get_num_polygon(); for ( int polygonIndex = 0; polygonIndex < polygonCount; polygonIndex++ ) { // Get the facet's data as a seq_polygon seq_polygon polygon; logical okay = mesh->get_seq_polygon( polygonIndex, polygon ); mesh_polygon* poly = &polygon; if ( !okay ) continue; // Is this a valid facet? If so, print the number of nodes. int nodeCount = poly->num_vertex(); if ( nodeCount <= 0 ) continue; fprintf( fp, "Face %d. Polygon %d\n", faceIndex, polygonIndex ); // Loop through each node of this facet, printing its data for ( int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++ ) { // Get the node's data as a polygon_vertex and print it polygon_vertex* vert = poly->get_vertex( nodeIndex ); if ( vert ) { SPAposition pos = vert->get_position(); SPAunit_vector vec = vert->get_normal(); SPApar_pos uv = vert->get_uv(); pos *= xform; vec *= xform; fprintf( fp, "position=(%f %f %f) normal=(%f %f %f) uv=(%f %f)\n", pos.x(), pos.y(), pos.z(), vec.x(), vec.y(), vec.z(), uv.u, uv.v ); } } // End braces for Loop through each node of this polygon } // End braces for Loop through each polygon } // End braces for Loop through each face }The call to get_seq_polygon is slower if the mesh is a LINKED_MESH (rather than an INDEXED_MESH). The improvement in faceting time should make up for this increase in time. With a little more work, we can avoid this increase in time as illustrated in the following example.
The extra code is in adding calls to the functions get_first_polygon, get_first_polynode, get_next_polygon, and get_next_polynode. Also, the calls to num_vertex are replaced by the call to get_num_polynode, and the calls to get_position, get_normal, and get_uv are slightly different. It is best to see the differences using any programmer's source code difference tool.
void writeSEQUENTIAL_MESH( ENTITY * inEntity, FILE* fp ) { // Get the transform on the body, if any. SPAtransf xform; ENTITY * owner; api_get_owner( inEntity, owner ); if ( is_BODY( owner ) ) { BODY * body; body = (BODY *)owner; if ( body->transform() ) xform = body->transform()->transform(); } ENTITY_LIST faceList; api_get_faces( inEntity, faceList ); // Loop through each face and print facet data for ( int faceIndex = 0; faceIndex < faceList.count(); faceIndex++ ) { FACE * face = (FACE*)faceList[faceIndex]; // Find the attribute for facets attached to the face. This is the mesh. MESH * face_mesh = NULL; af_query( (ENTITY*)face, IDX_MESH_APP, IDX_MESH_ID, face_mesh ); if ( face_mesh == NULL ) { printf( "No indexed mesh or linked mesh available for a face\n" ); continue; } SEQUENTIAL_MESH *mesh = (SEQUENTIAL_MESH*)face_mesh; // Loop through each facet and print its data int polygonCount = mesh->get_num_polygon(); // Get the handle of the first facet MESH_POLYGON meshPolygon; mesh->get_first_polygon( meshPolygon ); for ( int polygonIndex = 0; polygonIndex < polygonCount; polygonIndex++ ) { // Get the handle of the first node of the facet MESH_POLYNODE meshPolynode; if ( !mesh->get_first_polynode(meshPolygon, meshPolynode) ) continue; // Is this a valid facet? If so, print the number of nodes. int nodeCount = mesh->get_num_polynode(meshPolygon); if ( nodeCount <= 0 ) continue; fprintf( fp, "Face %d. Polygon %d\n", faceIndex, polygonIndex ); // Loop through each node of this facet, printing its data for ( int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++ ) { SPAposition pos = mesh->get_position( meshPolynode ); SPAunit_vector vec = mesh->get_normal( meshPolynode ); SPApar_pos uv = mesh->get_par_pos( meshPolynode ); pos *= xform; vec *= xform; fprintf( fp, "position=(%f %f %f) normal=(%f %f %f) uv=(%f %f)\n", pos.x(), pos.y(), pos.z(), vec.x(), vec.y(), vec.z(), uv.u, uv.v ); // Setup for the next loop by getting the next node of the facet mesh->get_next_polynode( meshPolynode ); } // End braces for Loop through each node of this polygon // Setup for the next loop by getting the next facet mesh->get_next_polygon( meshPolygon ); } // End braces for Loop through each polygon } // End braces for Loop through each face }
Related topics:
Refinements
Mesh Managers
Step-by-Step Faceting
Discarding or Keeping Facet Data
Faceting Functions and Classes
Faceting Using Scheme[Top]
© 1989-2007 Spatial Corp., a Dassault Systèmes company. All rights reserved.