Is there any way to make mesh-to-mesh collision?


I am making a toy project and I have to make mesh-to-mesh collision in this project.

If I set one block as ‘box’ collider, and another block as ‘mesh’ collider, It works well.

But If I set the both block as ‘mesh’ collider, It doesn’t work.

How can I make two ‘mesh collider’ blocks collide each other?


IIRC, bullet/ammo doesn’t support mesh - mesh dynamic collision. Your best bet is to compound primitives together to get an approximate shape.

The Bullet user manual seems to suggest otherwise as I commented on in another thread:

Ammo.js is currently using Bullet 2.8.2 (

AFAIK, it doesn’t support mesh mesh collision.

I had been reading the user manual for Bullet 2.8.3, but the manual for 2.8.2 (found here at the time of writing) says the same on this topic: Bullet has support for mesh-mesh collisions using the gimpact algorithm. However, btGimpactTriangleMeshShape (see figure 1 below) is missing from ammo.idl, suggesting that this is one of the features in Bullet that are currently not also in ammo.js, unfortunately.

Figure 1. Bullet 2.8.2 manual, page 18:

Figure 2. Bullet 2.8.2 manual, page 21:

Okay, I was under the impression that only btBvhTriangleMeshShape existed and that only supported static meshes.

You could add btGimpactTriangleMeshShape to your own compiled version of Ammo.js and add a patch to the engine to integrate it into PlayCanvas.

1 Like

I’m pursuing that option now. So far I have found out that:

  1. The user manual was wrong about btGimpactTriangleMeshShape. The correct interface to use, which actually exists in Bullet’s source code, is btGImpactMeshShape.
  2. PlayCanvas 1.22.0 (and probably other versions) is incompatible with builds of ammo.js newer than commit a96e001 from April 12 2017 where an async initialization API was introduced to ammo.js, so that instead of calling Ammo.x ... you need to do Ammo().then(ammo => ammo.x ...).

This engine patch you mention, do you suggest submitting it as a pull request to the PlayCanvas repo?

Regarding the custom patch, I would fork the engine and use the following docs to test and potentially deploy with it.

I think someone at PlayCanvas is working on updating to the latest ammo JS as well.

From the comments to this pull request, it appears you are right! :partying_face:

1 Like

This is now deployed. You can upgrade to the very latest WebAssembly-enabled build of Ammo.js now:

However, given the thread title, your reply might suggest that mesh-to-mesh collisions are now available in PlayCanvas, which they still aren’t, right?

Right. But now, you can use whatever version of ammo you like. You can go compile your own based on whatever IDL you like.

1 Like

You could try to use Ammo.btConvexHullShape instead of Ammo.btCompoundShape for dynamic mesh-to-mesh collisions. That’s how the CollisionMeshSystemImpl class could be rewritten:

(Try to paste this code somewhere before your entities are created) = function(entity, data) {
            if (typeof Ammo !== 'undefined' && data.model) {
                var model = data.model;
                var shape = new Ammo.btConvexHullShape();

                var i, j;
                for (i = 0; i < model.meshInstances.length; i++) {
                    var meshInstance = model.meshInstances[i];
                    var mesh = meshInstance.mesh;
                    var ib = mesh.indexBuffer[pc.RENDERSTYLE_SOLID];
                    var vb = mesh.vertexBuffer;

                    var format = vb.getFormat();
                    var stride = format.size / 4;
                    var positions;
                    for (j = 0; j < format.elements.length; j++) {
                        var element = format.elements[j];
                        if ( === pc.SEMANTIC_POSITION) {
                            positions = new Float32Array(vb.lock(), element.offset);

                    var indices = new Uint16Array(ib.lock());
                    var numTriangles = mesh.primitive[0].count / 3;

                    var v1 = new Ammo.btVector3();
                    var v2 = new Ammo.btVector3();
                    var v3 = new Ammo.btVector3();
                    var i1, i2, i3;

                    var base = mesh.primitive[0].base;
                    for (j = 0; j < numTriangles; j++) {
                        i1 = indices[base + j * 3] * stride;
                        i2 = indices[base + j * 3 + 1] * stride;
                        i3 = indices[base + j * 3 + 2] * stride;
                        v1.setValue(positions[i1], positions[i1 + 1], positions[i1 + 2]);
                        v2.setValue(positions[i2], positions[i2 + 1], positions[i2 + 2]);
                        v3.setValue(positions[i3], positions[i3 + 1], positions[i3 + 2]);
                        shape.addPoint(v1, true);
                        shape.addPoint(v2, true);
                        shape.addPoint(v3, true);


                var entityTransform = entity.getWorldTransform();
                var scale = entityTransform.getScale();
                var vec = new Ammo.btVector3();
                vec.setValue(scale.x, scale.y, scale.z);

                return shape;
            return undefined;

P.S. Didn’t test it well, but should work. After that you should be able to set body type to dynamic when using collsion type ‘mesh’.
P.P.S. Obviously, works with convex shapes only.

1 Like

Are there any updates on this? Is mesh to mesh collision still not possible, since the latest build of ammo does support it?

1 Like

So, is the wasm version included not a full fork of Ammo.js? I’m really interested in mesh-mesh collision, but I suppose it could be done another way. I’m working on a physics based dice roller that adds random torque to the dice and its coming along despite some errors I made modeling (setting the origin of the model affects the physics, by placing them above the origin, I set the “center of gravity” to always land baked side up.) So, it works pretty well except for mesh-mesh collisions will sometimes pass through each other or more troubling land through each other. So, I was going to write a script this morning to test collisions and realizing that might be more trouble than dynamically setting the collision shape to a box after they stop moving, and then applying a little opposite force.

It might be a slightly outdated version. But as it’s part of the project, you can replace it with a recent or your own custom version.

In my case I was just trying to make sure the dice don’t land overlapped, which you can achieve with a square trigger volume as the child, just a little smaller than the model, then check the event body for isStatic. Thanks for the help.

1 Like