kripken / ammo.js

Direct port of the Bullet physics engine to JavaScript using Emscripten
Other
4.15k stars 558 forks source link

btBvhTriangleMeshShape doesn’t seem to work #5

Closed cobbpg closed 12 years ago

cobbpg commented 13 years ago

The following code fails during the construction of btRigidBody:

var mesh = new Ammo.btTriangleMesh(true, true);
mesh.addTriangle(
    new Ammo.btVector3(0, 0, 0),
    new Ammo.btVector3(1, 0, 0),
    new Ammo.btVector3(0, 1, 0),
    false
);

var shape = Ammo.btBvhTriangleMeshShape(mesh, true, true);
var transform = new Ammo.btTransform();
transform.setIdentity();
var body = new Ammo.btRigidBody(
    new Ammo.btRigidBodyConstructionInfo(
        0,
        new Ammo.btDefaultMotionState(transform),
        shape,
        new Ammo.btVector3(0, 0, 0)
    )
);

The error message is the following:

ammo.js:2355: Uncaught TypeError: Cannot read property 'a' of undefined
kripken commented 13 years ago

The problem appears to be that you do shape = Ammo.btBvhTriangleMeshShape(.. and are missing the necessary new there.

This is an annoying problem with JavaScript. I guess we can add a null check in every constructor, but the cost is making the codesize bigger.

cobbpg commented 13 years ago

I don’t think that’s worth the extra cost, unless perhaps in a separate build for debugging purposes. It runs to completion after adding the missing new, but I still have issues with the resulting geometry. I’ll try to narrow it down to a trivial case.

cobbpg commented 13 years ago

Okay, I just returned to the WebStunts project and tried to port it to ammo.js again, since JigLibJS2 has some issues. The triangle mesh functionality in ammo.js seems to be really badly broken, and it behaves weirdly even in the simplest cases. Please download the current snapshot and check it out.

The staticMeshBody function takes a model whose faces are convex n-gons and feeds the faces into a btTriangleMesh as triangle fans. Choosing 16-bit indexes over 32-bit ones (setting the first parameter of the constructor false) affects the outcome for the levels, but not for the trivial cases. I figured I would try using btTriangleIndexVertexArray instead, but I couldn’t figure out how to pass the data to it from JavaScript; I’m not even sure if it is possible with the current version.

The trivial cases are at lines 774 to 787. All of them but the last three should work identically: catch the falling boxes way above the terrain (as the ones marked ‘Works’ do), since the geometry defines a big floating square that covers exactly the area of the track when looked at from above. Instead, they exhibit random behaviour. The last three cases are particularly interesting, since they define degenerate polygons with no area, yet they all behave as the full plane, so there’s clearly something nasty going on inside.

cjcliffe commented 13 years ago

I've noticed issues with the btTriangleMesh as well, I'm not positive yet but it seems specific to the static bvh collision shape -- note that providing the flag to 'Remove doubles' seems to help but there's still some random mangling of the geometry going on.

There are inherent issues in bullet/ammo with attempting to use extremely large triangles (very easy to fall through or get stuck in without a wide collision margin) but I'm seeing this with everything from low to high poly models of any scale..

I'll plan to write a test that will re-extract the contents of the btTriangleMesh using the debugDraw callback wrap to see if we can get a visual reference for what's going on in there -- will post an issue back to ammo.js if and when I can get a result.

As a temporary workaround I used compound collision shapes made of other primitives and convex point hulls where appropriate.

kripken commented 12 years ago

A test of some form would be much appreciated, very hard to figure out what is going on here without that.

In particular, a test with corresponding JS and C++ code would be perfect, then I can debug by comparing their processing.

cobbpg commented 12 years ago

It looks like the problem disappeared along the way. 16-bit indices still don’t work properly, but that’s not a problem in practice, since one can simply opt not to use them.