Three.js and ammo.js

Dear all,

I am fairly new to javascript and three.js. I have managed to load a custom 3D model using three.js. Now I want a ball to detect the “contour” of my 3D model. Except, I cannot manage to make it work and also I am trying to display the mesh that the ball should detect as collision and that does not work either. I will be grateful for your help. Please find my code below.

function createBaseMaze(){

    let pos = {x: 0, y: 0, z: 0};
    let scale = {x: 0.2, y: 0.2, z: 0.2};
    let quat = {x: 0, y: 0, z: 0, w: 1};
    let mass = 0;

    //Ammojs Section
    let concaveShape = new Ammo.btConvexHullShape();
    let transform = new Ammo.btTransform();
    let motionState = new Ammo.btDefaultMotionState( transform );
    let localInertia = new Ammo.btVector3( 0, 0, 0 );
    transform.setOrigin( new Ammo.btVector3( pos.x, pos.y, pos.z ) );
    transform.setRotation( new Ammo.btQuaternion( quat.x, quat.y, quat.z, quat.w ) );
    concaveShape.calculateLocalInertia( mass, localInertia );
    let rbInfo, body;

    console.log("MY Shape Before : ");
    loader = new GLTFLoader().setPath('');
    loader.load( 'Maze.gltf', async function ( gltf ) {

        model = gltf.scene;
        model.traverse( function ( child) {
                if(child instanceof THREE.Mesh) {
                    //Accéder à la géométrie du mesh
                    let geometry = child.geometry;
                    // Vérifier si la géométrie est un BufferGeometry
                    if (geometry instanceof THREE.BufferGeometry) {

                        // Obtenir les attributs de la géométrie
                        let positionAttribute = geometry.getAttribute('position');

                        // Récupérer les données des positions (sous forme de tableau TypedArray)
                        let positions = positionAttribute.array;

                        // Boucler à travers les données des positions pour former les triangles
                        for (let i = 0; i < positions.length; i += 9) {
                            // Créer un tableau pour stocker les coordonnées des sommets du triangle
                            //let triangle = [];

                            // Ajouter les coordonnées des sommets du triangle au tableau
                            let triangle = [
                                new Ammo.btVector3(positions[i], positions[i + 1], positions[i + 2]),
                                new Ammo.btVector3(positions[i + 3], positions[i + 4], positions[i + 5]),
                                new Ammo.btVector3(positions[i + 6], positions[i + 7], positions[i + 8])];

                            // Ajouter le triangle à la forme concave
                            concaveShape.addPoint(triangle[0], false);
                            concaveShape.addPoint(triangle[1], false);
                            concaveShape.addPoint(triangle[2], false);
                        console.log("number of positions is : ", positions.length);

            console.log("MY Shape : ", concaveShape.getNumVertices());
            rbInfo = new Ammo.btRigidBodyConstructionInfo( mass, motionState, concaveShape, localInertia );
            body = new Ammo.btRigidBody( rbInfo );
            physicsWorld.addRigidBody( body, colGroupPlane, colGroupRedBall );

            //addTriangleLines(scene, concaveShape);
        await renderer.compileAsync( model, camera, scene );
            scene.add( model );
        // onProgress callback
        function ( xhr ) {
            console.log( (xhr.loaded / * 100) + '% loaded' );
        // onError callback
        function ( err ) {
            console.error( 'An error happened' );

function addTriangleLines(scene, concaveShape) {
    const material = new THREE.MeshBasicMaterial({ color: 0xff0000, wireframe: true });

    // Boucler à travers chaque point de la forme concave
    for (let i = 0; i < concaveShape.getNumVertices(); i += 3) {
        // Obtenir les coordonnées des points pour former un triangle
        const pointA = concaveShape.points[i];
        const pointB = concaveShape.points[i + 1];
        const pointC = concaveShape.points[i + 2];

        // Créer la géométrie du triangle
        const geometry = new THREE.Geometry();
            new THREE.Vector3(pointA.x(), pointA.y(), pointA.z()),
            new THREE.Vector3(pointB.x(), pointB.y(), pointB.z()),
            new THREE.Vector3(pointC.x(), pointC.y(), pointC.z())
        geometry.faces.push(new THREE.Face3(0, 1, 2));

        // Créer le mesh du triangle et l'ajouter à la scène
        const triangleMesh = new THREE.Mesh(geometry, material);

I think you also need to iterate the geometry.index.array to get the vertex indices that form the triangle…

.indices contains the indices of the vertices forming each triangle… so iterate those 3 at a time… then get the vertex at each index.

What you have now looks like it’s just grabbing 3 unrelated vertices at a time.

Also getting ammo meshes/etc to work is tricky! But I think you’ll get it! :smiley:

Ammo has no visual part. You have to first create your visual object with THREE.JS, for example, with THREE.BufferGeometry()

then generate your Ammo shape with, for example, Ammo.btCompoundShape();
or Ammo.btConvexHullShape()

After passing the vertices from THREE.mesh to Ammo.Shape, then just create the physics. Ammo will do the calculations and Three will display the result

Lines: 521, 566

If possible, instead of creating a complex object, combine several simple objects with spheres and cubes to generate the appearance of the final object
Check Function: groupObj - Line 438

Thank you @didi_softwares and @manthrax, I will try to clean my code so threee meshes and ammo shapes are better identifed. I might try to use it with enable3D, this seems to facilitate my work.