Three.JS physics 2

Utiliser la physique dans Three.JS avec Ammo.js : Démolition d’un mur

Introduction – Avant de commencer

Dans cet exemple d’utilisation de la physique avec le couple Three.JS et Ammo.js, nous partirons de l’état final du code mis en place dans le chapitre précédent :

Dans ce chapitre, notre objectif sera de démolir un mur grâce à une collision physique. Si vous êtes prêts, commençons !

Ammo.js Wall
La destruction du mur !

Légères modifications de code

Reprenons le code du chapitre précédent, nous allons commencer nos modifications par une très légère refonte de la fonction createCube. Nous créons un paramètre color, utilisé pour préciser la couleur du cube.

Nous modifions également le paramètre scale. Initialement, ce paramètre était un simple Integer, nous le transformons en Vector3 pour pouvoir préciser une taille différente sur chaque axe XYZ.

Voici notre fonction createCube légèrement modifiée :

function createCube(scale , position, mass, color, rot_quaternion)
{
    let quaternion = undefined;

    if(rot_quaternion == null)
    {
        quaternion = {x: 0, y: 0, z: 0, w:  1};
    }
    else
    {
      quaternion = rot_quaternion;
    }

    // ------ Graphics Universe - Three.JS ------
    let newcube = new THREE.Mesh(new THREE.BoxBufferGeometry(scale.x, scale.y, scale.z), new THREE.MeshPhongMaterial({color: color}));
    newcube.position.set(position.x, position.y, position.z);
    scene.add(newcube);

    // ------ Physics Universe - Ammo.js ------
    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 defaultMotionState = new Ammo.btDefaultMotionState( transform );

    let structColShape = new Ammo.btBoxShape( new Ammo.btVector3( scale.x*0.5, scale.y*0.5, scale.z*0.5 ) );
    structColShape.setMargin( 0.05 );

    let localInertia = new Ammo.btVector3( 0, 0, 0 );
    structColShape.calculateLocalInertia( mass, localInertia );

    let RBody_Info = new Ammo.btRigidBodyConstructionInfo( mass, defaultMotionState, structColShape, localInertia );
    let RBody = new Ammo.btRigidBody( RBody_Info );

    physicsUniverse.addRigidBody( RBody );
    newcube.userData.physicsBody = RBody;
    rigidBody_List.push(newcube);
}

Mise en place de la scène

Une fois ces modifications terminées, retournons dans la fonction AmmoStart. Puis, utilisons createCube pour mettre en place les acteurs de notre scène.

Commençons par le support , le sol de notre scène dynamique :

createCube(new THREE.Vector3(50, 2, 90) , new THREE.Vector3(15, -5, 30) , 0 , 0x2c3e50, null);

Détaillons les paramètres utilisés :

  • scaleTaille sur les axes XYZ : (50, 2, 90).
  • positionPosition sur les axes XYZ : (15, -5, 30).
  • massMasse de notre objet : 0 (Masse infinie, objet statique).
  • colorCouleur de notre objet en hexadécimal : 0x2c3e50.
  • rot_quaternion – Quaternion, rotation initiale de l’objet : null donc {x: 0, y: 0, z: 0, w: 1} par défaut.

De la même façon, créons un bloc orienté en pente :

createCube(new THREE.Vector3(8, 1, 15) , new THREE.Vector3(15, 0, 0) , 0 , 0xffffff, {x: 0.383, y: 0, z: 0, w:  0.924} );

Ainsi, nous utilisons le paramètre rot_quaternion pour définir une rotation initiale, tourner l’objet et l’orienter en pente.

Voici nos deux blocs statiques :

Pente et sol ammo.js
Nos objets statiques – Le sol et la pente

Puis, toujours avec createCube, créons toutes nos briques dynamiques à l’aide de boucles :

for(var z = 30 ; z > 15 ; z -= 5)
{
    for(var j = 0 ; j < 10 ; j += 2.2)
    {
        for(var i = 0 ; i < 30 ; i += 2.1)
        {
          createCube(new THREE.Vector3(2, 2, 1.5) , new THREE.Vector3(i, j, z) , 1 , 0xffffff, null);
        }
    }
}

Ainsi, nous créons des briques empilées, de masse 1. Voici l’état actuel de notre scène :

Ammo.js wall
Nos briques dynamiques

Pour finir, créons un cube en chute libre au dessus de la pente. Ce dernier tombera sur le haut de la pente et sera propulsé vers les murs de briques :

setTimeout( function()
{
    createCube(new THREE.Vector3(6, 6, 6) , new THREE.Vector3(15, 500, -1) , 10000 , 0xc0392b, {x: 0.383, y: 0, z: 0.383, w:  0.924} );
}, 3000);

Nous choisissons de faire apparaître un cube de masse 10000 à une altitude 500, après un temps écoulé de 3 secondes (3000 ms).

Code final et résultat

Voici le code final de notre fonction AmmoStart :

function AmmoStart()
{
    tmpTransformation = new Ammo.btTransform();

    initPhysicsUniverse();
    initGraphicsUniverse();

    createCube(new THREE.Vector3(50, 2, 90) , new THREE.Vector3(15, -5, 30) , 0 , 0x2c3e50, null);


    for(var z = 30 ; z > 15 ; z -= 5)
    {
        for(var j = 0 ; j < 10 ; j += 2.2)
        {
            for(var i = 0 ; i < 30 ; i += 2.1)
            {
              createCube(new THREE.Vector3(2, 2, 1.5) , new THREE.Vector3(i, j, z) , 1 , 0xffffff, null);
            }
        }
    }

    createCube(new THREE.Vector3(8, 1, 15) , new THREE.Vector3(15, 0, 0) , 0 , 0xffffff, {x: 0.383, y: 0, z: 0, w:  0.924} );

    setTimeout( function()
    {
        createCube(new THREE.Vector3(6, 6, 6) , new THREE.Vector3(15, 500, -1) , 10000 , 0xc0392b, {x: 0.383, y: 0, z: 0.383, w:  0.924} );
    }, 3000);

    render();
}

Et pour finir ce chapitre, voici un aperçu de notre réalisation :

La destruction du mur

Un commentaire

Les commentaires sont fermés.