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.
I’m pursuing that option now. So far I have found out that:
The user manual was wrong about btGimpactTriangleMeshShape . The correct interface to use, which actually exists in Bullet’s source code, is btGImpactMeshShape .
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?
Great!
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?
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)
this.app.systems.collision.implementations.mesh.createPhysicalShape = 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 (element.name === 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);
shape.setLocalScaling(vec);
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.
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.
Update…
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.