playcanvas / engine

JavaScript game engine built on WebGL, WebGPU, WebXR and glTF
https://playcanvas.com
MIT License
9.57k stars 1.34k forks source link

Implement simple API to allow Meshes / Renders to be used as a Collider #4181

Open mvaligursky opened 2 years ago

mvaligursky commented 2 years ago

the complete story: https://forum.playcanvas.com/t/procedural-mesh-collision-generation-and-updates/25113

LeXXik commented 2 years ago

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

Maksims commented 2 years ago
  • 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.

dexterdeluxe88 commented 2 years ago

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

LeXXik commented 2 years ago

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.

jbromberg commented 1 year ago

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.

mvaligursky commented 1 year ago

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.

LeXXik commented 4 months ago

Related: #6265