Code viewer for World: Ammo for AB
 
// 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_instancing



const 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 -----------------

var ABloaded      = 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 );

    // floor
        
        var 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()
{
};