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 !
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 :
scale
– Taille sur les axes XYZ :(50, 2, 90)
.position
– Position sur les axes XYZ :(15, -5, 30)
.mass
– Masse de notre objet :0
(Masse infinie, objet statique).color
– Couleur 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 :
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 :
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 :
[…] August 27, 2021September 7, 2021 thomassifferlen Disponible en Français […]