// Three.js physics World using ammo.js // version for AB API// Highly modified port of "ammo / instancing" from Three.js examples// https://threejs.org/examples/?q=ammo#physics_ammo_instancingconst UNIT =2;// unit of distance const BOXSIZE = UNIT *0.1;const FLOORSIZE = UNIT *5;const LIGHTPOS = UNIT *5;const BOXTIMEOUT =300;// create new box every n milliseconds const startRadius = UNIT *2;const maxRadius = UNIT *1000;const SKYCOLOR ='lightblue';const TEXTURE_FILE_0 ='/uploads/starter/smiley.png';// textures for boxes const TEXTURE_FILE_1 ='/uploads/starter/ghost.3.png';var box_texture_0, box_texture_1 ;// 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 )));}function randomHighPos(){return( randomPos ( AB.randomFloatAtoB (1.5*UNIT,2*UNIT )));}
let physics;// ---- get AB loaded and physics loaded and then can create scene -----------------varABloaded=false;var physicsLoaded =false;
AB.runReady =false;
AB.world.newRun =function(){ABloaded=true;if(ABloaded&& physicsLoaded ) createScene();};
loadPhysics();
async function loadPhysics(){
physics = await AmmoPhysics();
physicsLoaded =true;if(ABloaded&& physicsLoaded ) createScene();}// -------------------------------------------------------------------------------------------function createScene(){// ready to create Three.js scene // define my own custom renderer and camera ABWorld.renderer =new THREE.WebGLRenderer({ antialias:true});ABWorld.renderer.setPixelRatio ( window.devicePixelRatio );ABWorld.renderer.shadowMap.enabled =true;ABWorld.renderer.outputEncoding = THREE.sRGBEncoding;ABWorld.camera =new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight,0.1, maxRadius );// near value of 0.1 to allow camera get closer to boxes ABWorld.init3d ( startRadius, maxRadius, SKYCOLOR );ABWorld.lookat.copy (ABWorld.scene.position );
loadResources();// asynchronous file loads // calls initScene() when all done }function loadResources(){var loader0 =new THREE.TextureLoader();var loader1 =new THREE.TextureLoader();
loader0.load ( TEXTURE_FILE_0,function( thetexture ){
thetexture.minFilter = THREE.LinearFilter;
box_texture_0 = thetexture;if( box_texture_0 && box_texture_1 ) initScene();});
loader1.load ( TEXTURE_FILE_1,function( thetexture ){
thetexture.minFilter = THREE.LinearFilter;
box_texture_1 = thetexture;if( box_texture_0 && box_texture_1 ) initScene();});}function initScene(){// files are loaded// ABWorld.scene is ready to be populated const hemiLight =new THREE.HemisphereLight();
hemiLight.intensity =0.35;ABWorld.scene.add( hemiLight );const dirLight =new THREE.DirectionalLight();
dirLight.position.set( LIGHTPOS, LIGHTPOS, LIGHTPOS );
dirLight.castShadow =true;
dirLight.shadow.camera.zoom =2;ABWorld.scene.add( dirLight );// floorvar floorGeometry =new THREE.BoxGeometry( FLOORSIZE, FLOORSIZE, FLOORSIZE );var floorMaterial =new THREE.ShadowMaterial({ color:0x111111});var floor =new THREE.Mesh( floorGeometry, floorMaterial );
floor.position.y =-2.5* UNIT;
floor.receiveShadow =true;ABWorld.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 // this is important - otherwise boxes fall forever // now the run can start ABWorld.render();
AB.runReady =true;
createBox();}function createBox(){// pick random one of the textures:var boxMaterial =new THREE.MeshLambertMaterial({ map: AB.randomPick ( box_texture_0, box_texture_1 )});var boxGeometry =new THREE.BoxGeometry( BOXSIZE, BOXSIZE, BOXSIZE );var box =new THREE.Mesh( boxGeometry, boxMaterial );
box.castShadow =true;
box.receiveShadow =true;
box.position.copy ( randomHighPos());// use copy to set position from a vector
box.rotation.set(Math.random()*Math.PI,Math.random()*Math.PI,Math.random()*Math.PI );ABWorld.scene.add( box );
physics.addMesh ( box,1);// has mass, so it falls
setTimeout ( createBox, BOXTIMEOUT );}
AB.world.nextStep =function(){};