Threejs Ammojs First Person Camera Collision Not Working with GLTF

Hi everyone, Can someone help me where is the problem in my code?
My GLTF model consists of walls, floor and ceiling

function initAmmoJsKinematicCharacterController(pos, quat, userData) {

    const radius = 1;
    const height = 3;

    let transform = new Ammo.btTransform();
    transform.setIdentity();
    transform.setOrigin(new Ammo.btVector3(1, 3, 1));
    transform.setRotation(new Ammo.btQuaternion(1, 1, 1, 1));

    let shape = new Ammo.btCapsuleShape(radius, height);
    shape.setMargin(0.05);

    bodyCapsuleShape = new Ammo.btPairCachingGhostObject();
    bodyCapsuleShape.setWorldTransform(transform);
    bodyCapsuleShape.setCollisionShape(shape);
    bodyCapsuleShape.setCollisionFlags(flags.CF_CHARACTER_OBJECT);
    bodyCapsuleShape.activate(true);

    kinematicCharacterController = new Ammo.btKinematicCharacterController(bodyCapsuleShape, shape, 0.35, 1);
    kinematicCharacterController.setUseGhostSweepTest(true);
    kinematicCharacterController.setUpInterpolate();
    kinematicCharacterController.setGravity(GRAVITY);
    kinematicCharacterController.setMaxSlope(Math.PI / 3);
    kinematicCharacterController.canJump(true);
    kinematicCharacterController.setJumpSpeed(GRAVITY / 3);
    kinematicCharacterController.setMaxJumpHeight(100);

    tmpVec3_ = new Ammo.btVector3(0, 0, 0);

    physicsWorld.addCollisionObject(bodyCapsuleShape);
    physicsWorld.addAction(kinematicCharacterController);

    const broadphase = physicsWorld.getBroadphase();
    const paircache = broadphase.getOverlappingPairCache();
    paircache.setInternalGhostPairCallback(new Ammo.btGhostPairCallback());

}

function createGLTFRigidBodyAsBox(model, position, quaternion, size, userData) {

    let transform = new Ammo.btTransform();
    transform.setIdentity();
    transform.setOrigin(new Ammo.btVector3(position.x, position.y, position.z));
    transform.setRotation(new Ammo.btQuaternion(quaternion.x, quaternion.y, quaternion.z, quaternion.w));

    let motionState = new Ammo.btDefaultMotionState(transform);

    let btSize = new Ammo.btVector3(size.x * 0.5, size.y * 0.5, size.z * 0.5);
    let shape = new Ammo.btBoxShape(btSize);
    shape.setMargin(0.05);

    let inertia = new Ammo.btVector3(0, 0, 0);
    shape.calculateLocalInertia(10, inertia);

    let info = new Ammo.btRigidBodyConstructionInfo(10, motionState, shape, inertia);
    let rigidBody = new Ammo.btRigidBody(info);

    var userData_ = new Ammo.btVector3(0, 0, 0);
    userData_.userData = userData;
    rigidBody.setUserPointer(userData_);

    rigidBody.setActivationState(4);
    rigidBody.setCollisionFlags(2);

    model.userData.physicsBody = rigidBody;

    physicsWorld.addRigidBody(rigidBody);

    rigidBody_List.push(model);

    /*Ammo.destroy(btSize);*/
}

 gltfLoader.load('models/house.glb', function (gltf) {

        scene_.add(gltf.scene);

        gltf.scene.children.forEach((element) => {
            createGLTFRigidBodyAsBox(element, element.position, element.quaternion, element.scale);
        });

    });


function updatePhysicsUniverse(timeElapsedS) {

    physicsWorld.stepSimulation(timeElapsedS, 10);

    for (let i = 0; i < rigidBody_List.length; i++) {

        let threeObject = rigidBody_List[i];
        let ammoObject = threeObject.userData.physicsBody;
        let motionState = ammoObject.getMotionState();
        if (motionState) {
            motionState.getWorldTransform(tempTransform);
            let pos = tempTransform.getOrigin();
            let quat = tempTransform.getRotation();
            threeObject.position.set(pos.x(), pos.y(), pos.z());
            threeObject.quaternion.set(quat.x(), quat.y(), quat.z(), quat.w());

        }

    }
}

does your gltf have nested children of children? if so the following code will only try to make colliders for the top level objects which may or may not be meshes…

gltf.scene.children.forEach((element) => {

try using the traverse method instead…

gltf.scene.traverse( element => {

  if(element.isMesh){
    createGLTFRigidBodyAsBox(element, element.position, element.quaternion, element.scale);
  }

})
2 Likes