Implement simple API to allow Meshes / Renders to be used as a Collider
- currently the Collider can accept Render / Model assets, or an instance of the model, which is not convenient for dynamically generated meshes
- Ammo tri-meshes are cached in the _triMeshCache and don't get removed, causing a leak. This should be implemented using ref counting similarly to how MeshInstance references a Mesh - when there are no references to tri-mesh, it needs to be properly released from the memory
the complete story: https://forum.playcanvas.com/t/procedural-mesh-collision-generation-and-updates/25113
To add to this:
At some point I had a need to use a convex hull for the shape. It can be generated via a convex decomposition by Ammo, where the input would still be a btTriangleMesh, but instead of using it to generate btBvhTriangleMeshShape like the collision system does, it would be used for btConvexHullShape:
const tmpConvexShape = new Ammo.btConvexTriangleMeshShape(triMesh);
const btConvexHullShape = new Ammo.btConvexHullShape(tmpConvexShape);
const btHull = new Ammo.btShapeHull(btConvexHullShape);
const margin = tmpConvexShape.getMargin();
btHull.buildHull(margin);
for (let i = 0; i < numTriangles; i++) {
i1 = indices[base + i * 3] * stride;
i2 = indices[base + i * 3 + 1] * stride;
i3 = indices[base + i * 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]);
btConvexHullShape.addPoint(v1, false);
btConvexHullShape.addPoint(v2, false);
btConvexHullShape.addPoint(v3, false);
}
btConvexHullShape.recalcLocalAabb();
Ammo.destroy(tmpConvexShape);
Ammo.destroy(btHull);
At the time, I remember that I had a thought it would be great if the Collision Component would have another type. Apart from primitive types, like box or sphere, it has only one option - "mesh". Which then uses btBvhTriangleMeshShape, that is used for static meshes. Perhaps, some kind of "user" shape type would be great, that would require the developer to provide the collision shape. There are quite a few that are a better fit for different purposes:
https://pybullet.org/Bullet/BulletFull/dir_0c2384ea07a1f9c912f061d6c891619f.html
- Ammo tri-meshes are cached in the _triMeshCache and don't get removed, causing a leak. This should be implemented using ref counting similarly to how MeshInstance references a Mesh - when there are no references to tri-mesh, it needs to be properly released from the memory
That is actually intended. And clearing a cache should be thought through, and a call by a developer. Developers can have a template of a car model with tri-mesh let's say, and they can instantiate them, then destroy, then instantiate again. And the only first time it will generate tri-mesh. But we cannot guarantee that there will be always at least one instance of it. So if application logic will have times with zero instances, this will lead to cache clearing, but that will lead to stalls next time we will instantiate the car model again.
So it should be a developer call to clear cache based on application logic, not automatic.
Somewhat related, as it is a conceptional decision whether it's the responsibility of the engine vs. the developer: https://github.com/playcanvas/engine/issues/1751
That is actually intended. So it should be a developer call to clear cache based on application logic, not automatic.
Not sure, if I agree here - the _triMeshCache is a variable private to the implementation system, indicated by the underscore. It is not supposed to be accessed outside of it. I doubt a developer is aware of it, unless they study the source code. If it is up to the developer to clear it, there should be a public API. Otherwise, the engine should handle it.
Would it be helpful to split this issue into 2 separate ones? It would be super useful to use a mesh/mesh instance as a collider. The cache seems to be a separate issue.
It's likely these would be implemented at the same time. But if somebody wants to develop just one part of it, they can create a PR just for that, there is no problem.
Related: #6265
I would also like to see better support for procedurally generated geometry. I'm porting my mesh fracturing library over to PlayCanvas and it's been very difficult figuring out how to massage the mesh data into a form that the CollisionComponent will accept.
I would also like to see better support for procedurally generated geometry. I'm porting my mesh fracturing library over to PlayCanvas and it's been very difficult figuring out how to massage the mesh data into a form that the
CollisionComponentwill accept.
This is very much needed! In the meantime sharing some pseudo-code on how to pass a custom mesh to the collision component the way we've been using it in our games (tested in PC v1 releases):
const mesh = new pc.Mesh(this.app.graphicsDevice);
mesh.setPositions(positions);
mesh.setNormals(normals);
mesh.setUvs(0, uvs);
mesh.setIndices(indices);
mesh.update();
this.entity.collision.render = {
meshes: [mesh]
};
This is very much needed! In the meantime sharing some pseudo-code on how to pass a custom mesh to the collision component the way we've been using it in our games (tested in PC v1 releases):
const mesh = new pc.Mesh(this.app.graphicsDevice); mesh.setPositions(positions); mesh.setNormals(normals); mesh.setUvs(0, uvs); mesh.setIndices(indices); mesh.update();
this.entity.collision.render = { meshes: [mesh] };
Thanks for this! Much cleaner approach than what was shared in the linked forum thread since you don't need to manually create a Render asset.