Ammo.js Pointer Methods

Despite using the ammo.js library quite a bit in my project I still don’t know what these methods do:
Ammo.wrapPointer, Ammo.getPointer , ammoObject.getUserPointer and ammoObject.getUserIndex

I sort of see how Ammo.getPointer works in conjunction with Ammo.wrapPointer:

foo = new Ammo.btVector3(1,2,3)
fooPointer = Ammo.getPointer(foo)
fooRetrieved = Ammo.wrapPointer(fooPointer, Ammo.btVector3)
fooRetrieved.x() === foo.x()
fooRetrieved.y() === foo.y()
fooRetrieved.z() === foo.z()

But that’s about all I could figure out.

I was also wondering if there was any identifying information I can stick on a particular ammo class instance if I wanted to be able to identify it later such as during an onHit callback.

Update: I did find this medium article:

Ammo.js on the other hand, deriving from its parent project bullet, also has a way to add the reference of a user object to a physics object. That mean we can also have our physics objects bear reference to their corresponding three.js object. This is achieved using the setUserPointer() and getUserPointer() methods of btCollisionObject ( parent class of btRigidBody ). With this we are able to retrieve our three.js objects if we have the physics objects at hand.

1 Like

Nice article :slight_smile: maybe @MackeyK24 would have some info about those

@MackeyK24 On aside, do you know how to detect collisions between a kinematic character controller and a rigid body? The normal methods don’t seem to be doing for me via:

export const setupContactPairResultCallback = (Ammo) => {
  const cbContactPairResult = new Ammo.ConcreteContactResultCallback()
  //@ts-ignore
  cbContactPairResult.hasContact = false
  /*
    for each contact point search:
      cbContactPairResult = callback object (results) for contactPairTest
      addSingleResult = method to search for colission between the 2 defined objects
      cp = contact point
      colObjWrap, colObj1Wrap = wrappers to retrieve participating object in collision
  */
  
  cbContactPairResult.addSingleResult = function(cp, colObj0Wrap, partId0, index0, colObj1Wrap, partId1, index1) {
    //@ts-ignore
    const contactPoint = Ammo.wrapPointer(cp, ammoInstance.btManifoldPoint)
    const distance = contactPoint.getDistance()
    console.log("here, distance: ", distance)
    if (distance > 0) return 0; /* theres no contact */
    //@ts-ignore
    cbContactPairResult.hasContact = true
    return 1
  }

  return cbContactPairResult
}

const cb = setupContactPairResultCallback()
const testBody = new Ammo.btRigidBody() /* assume it's scaled and positioned correctly */
physicsWorld.contactPairTest(testBody , player.controller.getGhostObject(), cb) // nothing happens

What does your btKinematicCharacterController setup look like… Make sure your ghost and character are setup right

this.m_ghostObject = new Ammo.btPairCachingGhostObject();
this.m_ghostObject.setWorldTransform(this.m_startTransform);
this.m_ghostObject.setCollisionShape(this.m_ghostShape);
this.m_ghostObject.setCollisionFlags(BABYLON.CollisionFlags.CF_CHARACTER_OBJECT);
this.m_ghostObject.setActivationState(4)
this.m_ghostObject.activate(true);                
// Create kinematic character controller
this.m_character = new Ammo.btKinematicCharacterController(this.m_ghostObject, this.m_ghostShape, this._stepOffset);
this.m_character.setUseGhostSweepTest(true);
this.m_character.setUpInterpolate(true);
this.m_character.setGravity(BABYLON.System.Gravity3G);
this.m_character.setMaxSlope(BABYLON.Tools.ToRadians(this._slopeLimit + 1));
// Add ghost object and character to world
world.addCollisionObject(this.m_ghostObject, BABYLON.CollisionFilters.CharacterFilter, BABYLON.CollisionFilters.AllFilter);
world.addAction(this.m_character);

I dont use the addSingleResult callback method… I poll for character controller collisions using m_ghostObject.getNumOverlappingObjects and m_ghostObject.getOverlappingObject in my update loop of my character controller class.

let contacts:number = this.m_ghostObject.getNumOverlappingObjects();
if (contacts > this._maxCollisions) contacts = this._maxCollisions;
if (contacts > 0) {
    for (let index = 0; index < contacts; index++) {
        const contactObject:any = this.m_ghostObject.getOverlappingObject(index);
        if (contactObject != null) {
            const contactBody:any = Ammo.castObject(contactObject, Ammo.btCollisionObject);
            if (contactBody != null && contactBody.entity != null && contactBody.isActive()) {

                // Is In Contact With Entity Object

            }
        }
    }
}
1 Like

@MackeyK24 that worked, thank you!

@sebavan @MackeyK24 Just thought I’d share what I learned:

foo = new Ammo.btRigidBody()
foo.setUserPointer(1234)
userPointer = foo.getUserPointer()
console.log(userPointer) // kE {bB: 1234}
userIndex = foo.getUserIndex()
console.log(userIndex) // 1234

I found the tests along side this particular file in the ammo.js repo to be pretty insightful: