See raw JS.
// Three.js physics World using ammo.js // Highly modified port of "ammo / instancing" from Three.js examples // https://threejs.org/examples/?q=ammo#physics_ammo_instancing AB.backgroundMusic ( '/uploads/starter/Interstellar.mp3' ); const UNIT = 2; // unit of distance const BOXSIZE = UNIT * 0.1 ; const FLOORSIZE = UNIT * 5 ; const LIGHTPOS = UNIT * 5 ; const NOBOXES = 100; // initial number of boxes - we then make more const BOXTIMEOUT = 200 ; // create new box every n milliseconds // random start positions for falling objects // x and z near origin, height y is argument: function randomPos ( y ) { return ( new THREE.Vector3 ( AB.randomFloatAtoB ( -0.5*UNIT, 0.5*UNIT ), y, AB.randomFloatAtoB ( -0.5*UNIT, 0.5*UNIT ) )); } // y is high or low: function randomHighPos() { return ( randomPos ( AB.randomFloatAtoB ( 1.5*UNIT, 2*UNIT ) )); } function randomLowPos() { return ( randomPos ( AB.randomFloatAtoB ( 0*UNIT, 2*UNIT ) )); } function randomColor() { return ( AB.randomPick ( 'firebrick', 'teal' )); } let camera, scene, renderer; let physics, boxes; init(); async function init() { physics = await AmmoPhysics(); camera = new THREE.PerspectiveCamera ( 60, window.innerWidth / window.innerHeight, 1, 1000*UNIT ); camera.position.set ( -UNIT, UNIT*1.5, UNIT*2 ); camera.lookAt ( 0, 0.5*UNIT, 0 ); scene = new THREE.Scene(); scene.background = new THREE.Color( 'lightblue' ); const dirLight = new THREE.DirectionalLight(); dirLight.position.set ( LIGHTPOS, LIGHTPOS, LIGHTPOS ); scene.add( dirLight ); // floor var floorGeometry = new THREE.BoxGeometry ( FLOORSIZE, FLOORSIZE, FLOORSIZE ); var floorMaterial = new THREE.MeshBasicMaterial ( { color: 'palegoldenrod' } ); var floor = new THREE.Mesh ( floorGeometry, floorMaterial ); floor.position.y = -2.5 * UNIT; scene.add( floor ); physics.addMesh ( floor, 0 ); // see function addMesh in AmmoPhysics.js // addMesh ( mesh, mass = 0 ) // floor has no mass - will not fall - will stay in place // boxes var boxGeometry = new THREE.BoxGeometry ( BOXSIZE, BOXSIZE, BOXSIZE ); var boxMaterial = new THREE.MeshLambertMaterial(); boxes = new THREE.InstancedMesh ( boxGeometry, boxMaterial, NOBOXES ); scene.add( boxes ); var matrix = new THREE.Matrix4(); for ( let i = 0; i < boxes.count; i++ ) { matrix.setPosition ( randomLowPos() ); boxes.setMatrixAt ( i, matrix ); var color = new THREE.Color ( randomColor() ); boxes.setColorAt ( i, color ); } physics.addMesh ( boxes, 1 ); // added with mass, so they fall // init Three.js renderer = new THREE.WebGLRenderer( { antialias: true } ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); renderer.outputEncoding = THREE.sRGBEncoding; document.body.appendChild( renderer.domElement ); createBox(); animate(); } function createBox() { var boxGeometry = new THREE.BoxGeometry ( BOXSIZE, BOXSIZE, BOXSIZE ); var boxMaterial = new THREE.MeshLambertMaterial ( { color: randomColor() } ); var box = new THREE.Mesh ( boxGeometry, boxMaterial ); box.position.copy ( randomHighPos() ); // use copy to set position from a vector scene.add( box ); physics.addMesh ( box, 1 ); // has mass, so it falls setTimeout ( createBox, BOXTIMEOUT ); // make new box is on a different timer to animate() } function animate() { requestAnimationFrame( animate ); // original code would make a "new" box as follows: // pick one box at random and suddenly move its position to up in the air to make the "new" box // strange effect - boxes vanishing at random // var i = AB.randomIntAtoB ( 0, boxes.count -1 ); // random 0 to (boxes.count - 1) // physics.setMeshPosition ( boxes, randomPos(), i ); // see function setMeshPosition in AmmoPhysics.js renderer.render( scene, camera ); }