Patching the CollisionSystemImpl.createAmmoMesh function by just switching the removeDuplicateVertices parameter at addTriangle to false makes our collision baking 10x or more faster. A 50k triangle mesh now gets generated in 15ms instead of 2000ms.
Since createAmmoMesh is essentially freezing the rendering, this improves user the experience a lot when Meshes get loaded dynamically.
The easiest (and dirtiest ) way to patch the engine behavior would be to patch addTriangle directly by adding the following lines of code anywhere before loading collision meshes:
Preferably, you want to remove the duplicate vertices in the modelling software. In Blender its simply a single command to remove them.
If you keep the duplicates and generate the collision mesh without removing them, as you do in your example, it will introduce degenerate triangles to the collision solver and some collisions will not be correct, e.g. dynamic objects clipping though, bouncing in the wrong direction, teleporting to the other side of the surface, jittering in place, etc.
That’s a great find!
Do you have some standalone repro for this? If so, could you create an issue here with it, I’m sure we can find some good solution for this.
Yes, true is the correct option. We want them to be removed. Do you mean it should not be hardcoded? I agree, it would be a good feature request, although, I don’t know if it will be more performant without dupes. This would need some benchmarking.
Well, it doesn’t matter, if it uses an index buffer or not. The reason they use false when adding a triangle, is because they know exactly that their mesh has no duplicates. The same would hold true if you remove them in Blender prior to generating the mesh.
You should never use false with the meshes that could potentially have duplicate vertices, e.g. directly using models downloaded from somewhere.
Maybe I am wrong, but when you take a look at the Ammo sample you will see that for every connected mesh there will be duplicate vertices generated, in fact it would lead to exactly the same inner structure with or without removed duplicates since 3 new vertices are added for each triangle:
/* vertices, faces */
let ammoMesh = new Ammo.btTriangleMesh();
for (let i = 0, l = faces.length; i < l; i++) {
let a = faces[i].a;
let b = faces[i].b;
let c = faces[i].c;
ammoMesh.addTriangle(
new Ammo.btVector3(vertices[a].x, vertices[a].y, vertices[a].z),
new Ammo.btVector3(vertices[b].x, vertices[b].y, vertices[b].z),
new Ammo.btVector3(vertices[c].x, vertices[c].y, vertices[c].z),
false
);
}
The only way to generate a collision mesh without duplicate vertices (without the flag) is by using indices. In this case, vertex duplicates should be removed before hand to be 100% safe as you said.
Well, firstly, under the hood addTriangle method is using addIndex and findOrAddVertex, so there is no difference if you use them directly or using addTriangle. And secondly, the only way to make findOrAddVertex to find an existing vertex is via the mentioned flag. If you pass false to it, it will always create a new vertex in the storage. So, in the end it doesn’t matter if you use indices or not - the result will be the same.
The only way to truly use indices, is to use .addTriangleIndices(i1, i2, i3). However, it is not available in Ammo, so we can only create new vertices and skip/no-skip the check for existing ones.
You can use findOrAddVertex by just adding each vertex once (assuming there are no duplicates in the mesh itself) and then adding the 3 indices per triangle, hence no duplicates.
Ah, I see what you mean now Thank you for the example! Yes, I agree with you.
I will add it to the feature request, as an implementation option.
As for the duplicate vertices - the issue will be visible in games, like golf, when you try to roll a dynamic ball on a surface with degenerate triangles. A raycast vehicle would probably be fine, as the ray should always hit the healthy triangle? Not sure. For kinematic controllers and some dynamic debris it should be fine or at least not obviously visible to player.