kripken / ammo.js

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

Wrong Pointer of Body in ConcreteContactResultCallback #230

Open RaggarDK opened 5 years ago

RaggarDK commented 5 years ago

I have an issue with determining which bodies are involved in colliding with my btGhostObject.

This is how I create my btGostObject: ghost = new Ammo.btGhostObject(); ghost.setCollisionShape(new Ammo.btSphereShape(10)); ghost.setWorldTransform(new Ammo.btTransform(new Ammo.btQuaternion(0,0,0,1),new Ammo.btVector3(0,15,0))); ghost.setCollisionFlags( 4 ); physicsWorld.addCollisionObject(ghost);

This is how I create my ConcreteContactResultCallback: AmmoConcreteContactResultCallback = new Ammo.ConcreteContactResultCallback(); AmmoConcreteContactResultCallback.addSingleResult = function( manifoldPoint, collisionObjectA, id0, index0, collisionObjectB, id1, index1 ) {console.log(collisionObjectA); var bodyA = Ammo.wrapPointer(collisionObjectA, Ammo.btCollisionObject); var uBodyA = Ammo.btRigidBody.prototype.upcast(bodyA); var body = Ammo.castObject(bodyA, Ammo.btRigidBody); console.log(uBodyA); console.log(body); }

And this is how I use it in the game loop: physicsWorld.contactTest(ghost, AmmoConcreteContactResultCallback);

Now, I know that the body colliding with the ghostObject has pointer 8772560, while the pointer given for the collision is different(27824). Both collisionObjectA and collisionObjectB have pointers in the 27xxx range. Using the above two ways of upcasting the bodies fail, as the pointers are wrong. uBodyA gives a new? body with a 0 pointer, and body gives a new? body with a 27824 pointer. I guess the issue happens before the upcast, since the pointers are wrong, but I can't seem to find the issue.

anemol commented 5 years ago

I have the same problem than you. Have you find a solution?

To know if i can place an object in my physics world, i use a btGhostObject. All my objects have a userpointer to retrieve information about them.

The detection of the free space works fine but it is impossible to retrieve which rigibodies are concerned, so, i guess, the pointers returned are wrong.

var isFreeSpot;
resultCallback = new Ammo.ConcreteContactResultCallback();
resultCallback.addSingleResult = function(manifoldPoint,collisionObjectA,id0,index0,collisionObjectB,id1,index1) {
    isFreeSpot=false;
   [collisionObjectA,collisionObjectB].forEach(function(pointer)
    {
        var collisionObject = Ammo.wrapPointer(pointer,Ammo.btCollisionObject);
        var rigidBody=Ammo.btRigidBody.prototype.upcast(collisionObject);   
        var myData=Ammo.castObject(rigidBody.getUserPointer(), Ammo.btVector3 ).myData;
        console.log(myData); // all time "undefined"
    });
}
// Check if placable
var ghost = new Ammo.btGhostObject(); 
var shape= new Ammo.btSphereShape(0.25);
ghost.setCollisionShape(shape); 
var transform = new Ammo.btTransform();
transform.setIdentity();
tempVector.setValue(x,y,z); //reusable vector3
transform.setOrigin(tempVector); 
ghost.setWorldTransform(transform);
ghost.setCollisionFlags( 4 );  // no effect
var btVecUserData = new Ammo.btVector3( 0, 0, 0 );
btVecUserData.myData = {id:'ghost',name:"ghost"};
ghost.setUserPointer(btVecUserData);

isFreeSpot=true;
//dynamicsWorld.addCollisionObject(ghost);
dynamicsWorld.contactTest(ghost, resultCallback);
//dynamicsWorld.removeCollisionObject(ghost);

if (isFreeSpot) {
....
} else {
 ....
}
Ammo.destroy(ghost);
Ammo.destroy(shape);
Ammo.destroy(btVecUserData);
Ammo.destroy(transform)
anemol commented 5 years ago

I may have found a way for this to work.

According to the source of Bullet (https://pybullet.org/Bullet/BulletFull/structbtCollisionWorld_1_1ContactResultCallback.html), btCollisionObjectWrapper is used.

So, i modified btCollisionObject with btCollisionObjectWrapper and added getCollisionObject for btCollisionObjectWrapper and compiled.

ammo.idl:

[NoDelete]
interface btCollisionObjectWrapper {
    [Const] btCollisionObject   getCollisionObject ();
};

[Prefix="btCollisionWorld::"]
interface ContactResultCallback {
  float addSingleResult([Ref] btManifoldPoint cp, [Const] btCollisionObjectWrapper colObj0Wrap, long partId0, long index0, [Const] btCollisionObjectWrapper colObj1Wrap, long partId1, long index1);
};

[JSImplementation="ContactResultCallback"]
interface ConcreteContactResultCallback {
  void ConcreteContactResultCallback();
  float addSingleResult([Ref] btManifoldPoint cp, [Const] btCollisionObjectWrapper colObj0Wrap, long partId0, long index0, [Const] btCollisionObjectWrapper colObj1Wrap, long partId1, long index1);
};

root.h:

class ConcreteContactResultCallback : public btCollisionWorld::ContactResultCallback // for JS callbacks through vtable customization
{
public:
  ConcreteContactResultCallback() {};
  virtual float addSingleResult(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0,int partId0,int index0,const btCollisionObjectWrapper* colObj1,int partId1,int index1) { return 0; };
};

And my code is:


resultCallback.addSingleResult = function(  manifoldPoint,collisionObjectWrapperA,id0,index0,collisionObjectWrapperB,id1,index1) 
{
    isFreeSpot=false;

    var collisionObjectA = Ammo.wrapPointer(collisionObjectWrapperA,Ammo.btCollisionObjectWrapper).getCollisionObject();
    var collisionObjectB = Ammo.wrapPointer(collisionObjectWrapperB,Ammo.btCollisionObjectWrapper).getCollisionObject();

    var myDataA=Ammo.castObject(collisionObjectA.getUserPointer(), Ammo.btVector3 ).myData;
    var myDataB=Ammo.castObject(collisionObjectB.getUserPointer(), Ammo.btVector3 ).myData; ```