Tutorial 10: Mesh Shapes



Note: The instructions in this tutorial refer to versions of OPAL after 0.3.0 (including the CVS version).  Meshes in versions 0.3.0 and earlier had problems that made them unusable.


This tutorial describes how to use mesh Shapes.  Although this process is more complex than using primitive Shapes like boxes and spheres, it allows you to use your own triangle mesh for collision detection.  There are four pieces of data that are necessary to create a mesh: the number of vertices, an array of vertex data, the number of triangles, and an array of indexed triangle data.  No matter how you get your geometry data (e.g. loading it from an OBJ file, generating it programmatically at runtime, etc.), it must be represented in this format.


The vertex and triangle arrays must be 1-dimensional arrays.  The size of the vertex array is 3 times the number of vertices since each vertex uses three elements (for its x, y, and z components).  Similarly, the triangle array is 3 times the number of triangles since each triangle uses three vertices.  The following diagrams show how these arrays must be organized:



The indexed triangle array stores the indices of vertices in the vertex array.  For example, in the diagram above, “triangle 2” uses vertices 1, 2, and 4 in the vertex array.  This storage method is fairly common; it allows vertices to be reused by multiple triangles. 


The following example shows how to copy your geometry data into the MeshShapeData structure.  This example assumes that the geometry is initially stored in 2-dimensional arrays.




opal::Simulator* sim = opal::createSimulator();

opal::Solid* s = sim->createSolid();

opal::MeshShapeData meshData;


// ‘vertices’ is a 2-dimensional array of vertex data, ‘triangles’ is

// a 2-dimensional array of triangle data, ‘vertexCount’ is the number

// of vertices in the vertex array, and ‘triangleCount’ is the number

// of triangles in the triangle array.  All of this data must be loaded

// from a file or generated programmatically.


meshData.numVertices = vertexCount;

meshData.numTriangles = triangleCount;


// Allocate vertex and triangle arrays.

meshData.vertexArray = new opal::real[3 * meshData.numVertices];

meshData.triangleArray = new unsigned int[3 * meshData.numTriangles];


// Copy vertex data.

for (unsigned int i = 0; i < meshData.numVertices; ++i)


    meshData.vertexArray[i * 3] = vertices[i][0];

    meshData.vertexArray[i * 3 + 1] = vertices[i][1];

    meshData.vertexArray[i * 3 + 2] = vertices[i][2];



// Copy triangle data.

for (unsigned int i = 0; i < meshData.numTriangles; ++i)


    meshData.triangleArray[i * 3] = triangles[i][0];

    meshData.triangleArray[i * 3 + 1] = triangles[i][1];

    meshData.triangleArray[i * 3 + 2] = triangles[i][2];







// Remember to deallocate the data when totally finished with

// the simulation (be sure to keep it around during the simulation,

// though).  Here is one way to do this..

opal::SolidData solidData = s->getData();

for (unsigned int i = 0; i < solidData.getNumShapes(); ++i)


    if (solidData.getShapeData(i)->getType() == opal::MESH_SHAPE)


        opal::MeshShapeData* meshData =



        delete [] meshData->vertexArray;

        delete [] meshData->triangleArray;
























































OPAL is Copyright © 2004-2005 Alan Fischer, Andres Reinot, and Tyler Streeter