Mesh Collision in PhysX


Apart from the simple shapes as a cube or capsule, PhysX allows for Convex Meshs and Triangle Meshs to represent more complex collision objects. Unfortunately, it is usually not possible to use the 3D triangle mesh used for display purpose as-it-is for collision detection. Also it is very important to keep in mind that mesh collision is a computationally expensive operation and should be avoided when possible. Another important fact is that Triangle Mesh to Triangle Mesh collision is not supported by PhysX.

A 3D triangle mesh is loaded into OpenGL or DirctX as a list vertexes in the form of XYZ coordinate triplets (v0,v1,v2), triangles as a list of indexes referring to the previous defined vertexes, may have vectors representing the triangles surface normal (indicating the side of the triangle where the texture would be mapped to facing “outwards”), texture pointers (or materials) associated with the triangles and eventually animation information. A small piece of a model in obj format:

v 0.014000 -0.039000 0.012000 //vertex position

v 0.014000 0.039000 0.012000

usemtl MediumGrey //Material information

f 196 209 235 //triangle (or face) information

f 209 215 235

In order to transform a 3D triangle mesh into a collision object PhysX provides an application framework. This process is called cooking by PhysX documentation. The mesh provided as input cooking rarely should be the same than the one being shown on screen, because of the excess of detail and consequent overhead in the physics calculation. A simplified model should be used, this model may, for instance, be convex (which provides significant less overhead in the simulation)  and should consider other minor aspects, such as, reduction of vertex duplication.

When the mesh is ready it needs to be “cooked” by PhysX, this process can be long but is a one-time-only operation. The output is file in binary format that is optimized for collision detection and can be easily loaded in the shape it represents at run-time. The following code uses the PhysX SDK’s 3DS model wrapper that contains the 3d rendering mesh (other file types and wrappers will have different parameters) and “cooks” it into a collision mesh.


Model_3DS* m = (Model_3DS*)(((ShapeUserData*)robot->getShapes()[0]->userData)->model);

bool success = gCooking->NxCookTriangleMesh(Desc, UserStream(“C:/cooked.bin”, false));
NxCookingInterface *gCooking = NxGetCookingLib(NX_PHYSICS_SDK_VERSION);
//Build physical model
NxTriangleMeshDesc Desc;
Desc.numVertices = m->Objects[0].numVerts;
Desc.numTriangles = m->Objects[0].numFaces/3;
Desc.pointStrideBytes = sizeof(Vertex);
Desc.triangleStrideBytes = 3*sizeof(unsigned short);
Desc.points = m->Objects[0].Vertexes;
Desc.triangles = m->Objects[0].Faces;
Desc.flags = NX_MF_16_BIT_INDICES;
bool valid = Desc.isValid();
bool success = gCooking->NxCookTriangleMesh(Desc, UserStream(“C:/cooked.bin”, false));

In my experience I had another curious difficulty, nothing returned errors but I could not see the mesh. Turns out it was the scale. The scale of a cooked collision mesh (convex or triangle) cannot be changed, so be sure to define the scales used before hand.

Upon doing so it is only necessary to create a TriangleMeshDescriptor load the mesh in, associate it with a Shape, the Shape with the Actor and collision is ready!

The tiny TriangleMesh:

The final Triangle Mesh in red on top of the rendered mesh in blue:

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: