// Cloned by Leigh Reilly on 30 Nov 2022 from World "Complete Infinite World" by Enhanced
// Please leave this clone trail here.
//==============================================================================
// Welcome to the Infinite world !
//==============================================================================
// This program was made by Nathan Bonnard.
// In this world, you can generate an infinite world !
// But this isn't really infinite, it would be impossible,
// the world do a simple loop when the player reach the border. Like in real life !
// This world isn't a kind of game with specific goal, just enjoy the landscapes and all objects !
//
// The first purpose of this world was to create an exploration world to just enjoy good views and the fact that it is infinite
// Finally it became a sort of Minecraft, I wanted to create that type of game but with complex 3D Objects, not cubes.
// I wanted to demonstrate the power of javascript and Three.js : we can create big world with a lot of objects even in a browser
// Also, the aim is to encourage people using the first person view on worlds or the sun that you can find on Enhanced World.
// If you want to change the world by yourself, it would be a bit hard to get into 2000 lines of code,
// but you can simply change some letiables and see the effects. Here are those letiables :
//------------------------------ TWEAKER BOX ------------------------------//
const squaresize = 5 ; // The world is like a infinite grid of square. squaresize is the size of a square
var MOVESPEED = 7; // Speed of the player
var viewDistance = 2; // determinate the maximum distance to see ground (viewDistance * squaresize * groundMultiplier)
var groundMultiplier = 551; // The world is divided by zone (grounds) that size groundMultiplier*squaresize
var worldSize = 13; // dimension of the world, it is not really infinite but big and can loop. There is worldSize * worldSize Grounds
const SKYDISTANCE = 3000; // Distance of stars and sun
const NBSTARS = 100; //number of stars
//Where all textures and objects are
const PATHTEXTURES = "/uploads/meak/";
//Limit between rare and small objects (in term of size, obviously here a castle size is bigger than 4 but a rock is not)
//Care it depends on the squaresize letiable. If you increase squaresize, you should also decrease this letiable
const limitSizeForRareObjects = 2;
//Number of maximum element that can be pose in each ground. You can change this after running the world
var maxElementsForest = 300;
var maxElementsSnow = 90;
var maxElementsSand = 60;
//Determine if the world can or not generate different type of ground. You can change this after running the world
var enableSand = true;
var enableSnow = true;
var enableForest = true;
//Path of sounds that are played during the game depending on what type of ground you are walking on
// const SOUNDFOREST = "/uploads/meak/forestsound.mp3";
// const SOUNDSNOW = "/uploads/meak/snowsound.mp3";
// const SOUNDSAND = "/uploads/meak/sandsound.mp3";
// const SOUNDNIGHT = "/uploads/meak/nightsound.mp3";
//Objects that are loaded for each type of ground. Add some Objects that you found on the internet and see !
//For that it need to be an Object3D (.obj) with a material (.mtl).
//If the material need some texture, upload those textures too.
const ARRAYOBJECTSFOREST = {
"tree2":40,
"lowpolytree":30,
"castle-tower":0.5,
"WoodenCabinObj":1,
"houseA_obj":1,
"tree13":30
};
const ARRAYOBJECTSSNOW = {
"castle-tower":0.5,
"Stone":15,
"kardanadam":2,
"WoodenCabinObj":1,
"Rock2":1
};
const ARRAYOBJECTSSAND = {
"castle-tower":0.5,
"Cactus":10,
"Stone":15,
"WoodenCabinObj":1,
"houseA_obj":1,
"Rock2":1
};
//------------------------------ END OF TWEAKER BOX ------------------------------//
var newviewDistance = viewDistance; // letiables to re-generate the world with new letiables
var newGroundMultiplier = groundMultiplier;
var newworldSize = worldSize;
const MAXPOS = 4000 ;
const startRadiusConst = MAXPOS * 0.5 ; // distance from centre to start the camera at
const maxRadiusConst = MAXPOS * 5 ; // maximum distance from camera we will render things
const SKYCOLOR = 0x6495ED;
const LIGHTCOLOR = 0xffffff ;
//all type of Grounds
const TYPEGROUND = ["SNOW", "FOREST", "SAND"];
//used to manage the click and give back control to the user when you click on a button/text box
//and don't want to enter into first person mode
var HUDEVENT = false;
var mouse; // vector2 : position of the mouse on the screen
threehandler.MAXCAMERAPOS = MAXPOS * 10 ;// allow camera go far away
threeworld.drawCameraControls = false;
AB.clockTick = 20;
// Speed of run: Step every n milliseconds. Default 100.
AB.maxSteps = 1000000;
// Length of run: Maximum length of run in steps. Default 1000.
AB.screenshotStep = 50;
// Take screenshot on this step. (All resources should have finished loading.) Default 50.
/**
* A linear interpolator for hexadecimal colors
* @param {Int} a
* @param {Int} b
* @param {Number} amount
* @example
* // returns 0x7F7F7F
* lerpColor(0x000000, 0xffffff, 0.5)
* @returns {Int}
*/
function lerpColor(a, b, amount) {
let ah = a;
ar = ah >> 16, ag = ah >> 8 & 0xff, ab = ah & 0xff,
bh = b;
br = bh >> 16, bg = bh >> 8 & 0xff, bb = bh & 0xff,
rr = ar + amount * (br - ar),
rg = ag + amount * (bg - ag),
rb = ab + amount * (bb - ab);
return ((1 << 24) + (rr << 16) + (rg << 8) + rb | 0);
}
/**/
function map(n, start1, stop1, start2, stop2)
{
return ((n-start1)/(stop1-start1))*(stop2-start2)+start2;
}
//==============================================================================
// World Definition
//==============================================================================
function World() {
//==============================================================================
// All variables
//==============================================================================
var objects; // Stock all the prefabs of objects
var groundTexture; // Texture of the ground
var snowTexture; // Texture of the ground
var sandTexture; // Texture of the ground
var transitionTextureSnow;
var transitionTextureSand;
var transitionTextureForest;
var loaded = false; // True when everything is loaded
var grounds; // Array2d : Stock all ground of the world, with objects on it (recurrentObjects...)
var ai, aj; // position in grounds of the player
var pai, paj; // past position in grounds of the player
var modeOfView = 0; //0 : first person --- 1 : third person
var timeRunning = 0; // time updated
var raycaster; // to determine direction of a click
var camera, controls;
var moveForward = false;
var moveBackward = false;
var moveLeft = false;
var moveRight = false;
var canJump = false;
var prevTime = performance.now();
var velocity = new THREE.Vector3();
var direction = new THREE.Vector3();
var vertex = new THREE.Vector3();
var color = new THREE.Color();
//var sun;//sun and all functions with it (also stars)
var loadingManager;//loading manager to load everything and thenrun the program
//var soundManager;//Object that manage the sound depending of the position of the player
var saving; //Object that store all informations to save the world
var offsetGround = 0.001;//letiable to avoid that grounds "bug" when they to parcels are overlapping
var userObjects = [];//store all objects that were pose by the player in edit mode
var allObjects = [];//allTypeOfObjects tht can be created by the player in edit mode
var indexObjects = 0;//Usefull to manage userObjects
var rayToDestroy;
var selectionBox = new THREE.Mesh();
var selectionObject = null;
var editMode = null;
this.endCondition = false;
}
//==============================================================================
//==============================================================================
//==============================================================================
// All Class
//==============================================================================
//==============================================================================
// Defines the THREE.PointerLockControls class, source at https://threejs.org/
//==============================================================================
THREE.PointerLockControls = function(camera) {
let scope = this;
camera.rotation.set( 0, 0, 0 );
let pitchObject = new THREE.Object3D();
pitchObject.add( camera );
let yawObject = new THREE.Object3D();
yawObject.position.y = 10;
yawObject.add( pitchObject );
let attachedObject = new THREE.Object3D();
yawObject.add(attachedObject);
attachedObject.position.set(0,-yawObject.position.y,-150);
let PI_2 = Math.PI / 2;
let onMouseMove = function ( event ) {
if ( scope.enabled === false ) return;
if(editMode == 1)
{
if(controls.getAttachedObject().children.length != 0)
{
controls.getAttachedObject().remove(controls.getAttachedObject().children[1]);
controls.getAttachedObject().remove(controls.getAttachedObject().children[0]);
}
DestroyObject(event);
}
let movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0;
let movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0;
yawObject.rotation.y -= movementX * 0.002;
pitchObject.rotation.x -= movementY * 0.002;
pitchObject.rotation.x = Math.max( - PI_2, Math.min( PI_2, pitchObject.rotation.x ) );
};
this.getAttachedObject = function () {
return attachedObject;
};
this.dispose = function () {
document.removeEventListener( 'mousemove', onMouseMove, false );
};
document.addEventListener( 'mousemove', onMouseMove, false );
this.enabled = false;
this.getObject = function () {
return yawObject;
};
this.getDirection = function () {
// assumes the camera itself is not rotated
let direction = new THREE.Vector3( 0, 0, - 1 );
let rotation = new THREE.Euler( 0, 0, 0, 'YXZ' );
return function ( v ) {
rotation.set( pitchObject.rotation.x, yawObject.rotation.y, 0 );
v.copy( direction ).applyEuler( rotation );
return v;
};
}();
};
//==============================================================================
//Class to save the world
// class SaveWorld
// {
// constructor(dim, mult, viewDistance)
// {
// this.worldSize = dim;
// this.groundMultiplier = mult;
// this.viewDistance = viewDistance;
// this.grounds = new Array(dim);
// for(let i = 0; i < this.grounds.length; i++)
// {
// this.grounds[i] = new Array(dim);
// for(let j = 0; j < this.grounds[i].length; j++)
// {
// this.grounds[i][j] = {biom: "", elements:[]};
// }
// }
// this.userObjects = [];
// }
// }
// Class to stock Each Objects that were loaded
// with their combobox size to place them in space
// and to avoid collision ( objects at same place)
class Obj
{
constructor(nameDoc, sX, sY, sZ)
{
this.path = nameDoc;
this.sizeX = sX;
this.sizeY = sY;
this.sizeZ = sZ;
this.obj;
}
}
//Class that determine if a ground is active or not
//And stock the ground with all the objects attached
class Ground
{
constructor(act, pos)
{
this.active = act;
this.ground;
this.type;
}
}
//Class that stock all the objects of all types
class ObjectsConteneur
{
constructor()
{
this.objectsForest = new ObjectsOfType("FOREST");
this.objectsSand = new ObjectsOfType("SAND");
this.objectsSnow = new ObjectsOfType("SNOW");
}
}
//Class that stock all the objects of the different type
class ObjectsOfType
{
constructor(type)
{
this.type = type;
this.recurrentObjects = [];
this.rareObjects = [];
}
}
//Class that deal with the sound
// class SoundManager
// {
// constructor()
// {
// let listener = new THREE.AudioListener();
// threeworld.camera.add( listener );
// // create a global audio source
// this.soundForest = new THREE.Audio( listener );
// this.soundSand = new THREE.Audio( listener );
// this.soundSnow = new THREE.Audio( listener );
// this.soundNight = new THREE.Audio( listener );
// this.currentSound = null;
// this.isNight = false;
// }
// playCurrentSound()
// {
// if(this.currentSound != null)
// {
// if(this.isNight)
// {
// this.soundNight.setVolume(0);
// this.soundNight.play();
// }
// else if(this.currentSound == "FOREST")
// {
// this.soundForest.setVolume(0);
// this.soundForest.play();
// }
// else if(this.currentSound == "SAND")
// {
// this.soundSand.setVolume(0);
// this.soundSand.play();
// }
// else if(this.currentSound == "SNOW")
// {
// this.soundSnow.setVolume(0);
// this.soundSnow.play();
// }
// }
// }
// updateSound()
// {
// if(this.currentSound != null)
// {
// if(this.isNight && this.soundNight.getVolume() < 0.5)
// {
// this.soundNight.setVolume(this.soundNight.getVolume() + 0.01);
// }
// else if(this.currentSound == "FOREST" && this.soundForest.getVolume() < 0.5)
// {
// this.soundForest.setVolume(this.soundForest.getVolume() + 0.01);
// }
// else if(this.currentSound == "SAND" && this.soundSand.getVolume() < 0.5)
// {
// this.soundSand.setVolume(this.soundSand.getVolume() + 0.01);
// }
// else if(this.currentSound == "SNOW" && this.soundSnow.getVolume() < 0.5)
// {
// this.soundSnow.setVolume(this.soundSnow.getVolume() + 0.01);
// }
// if((this.currentSound != "FOREST" || this.isNight) && this.soundForest.getVolume() > 0)
// {
// this.soundForest.setVolume(this.soundForest.getVolume() - 0.01);
// if(this.soundForest.getVolume() <= 0)
// {
// this.soundForest.stop();
// }
// }
// if((this.currentSound != "SAND" || this.isNight) && this.soundSand.getVolume() > 0)
// {
// this.soundSand.setVolume(this.soundSand.getVolume() - 0.01);
// if(this.soundSand.getVolume() <= 0)
// {
// this.soundSand.stop();
// }
// }
// if((this.currentSound != "SNOW" || this.isNight) && this.soundSnow.getVolume() > 0)
// {
// this.soundSnow.setVolume(this.soundSnow.getVolume() - 0.01);
// if(this.soundSnow.getVolume() <= 0)
// {
// this.soundSnow.stop();
// }
// }
// if(!this.isNight && this.soundNight.getVolume() > 0)
// {
// this.soundNight.setVolume(this.soundNight.getVolume() - 0.01);
// if(this.soundNight.getVolume() <= 0)
// {
// this.soundNight.stop();
// }
// }
// }
// }
// }
//Sun, used like a class
// let Sun = function()
// {
// this.angle = 0;
// this.object = new THREE.DirectionalLight( 0xffffff, 0.1 );
// this.object.position.set(0, Math.cos(this.angle)*3000, Math.sin(this.angle)*3000);
// this.object.castShadow = true;
// this.object.shadow.mapSize.width = 1024;
// this.object.shadow.mapSize.height = 1024;
// this.object.shadow.camera.near = 10;
// this.object.shadow.camera.far = 4000;
// let d = 1000;
// this.object.shadow.camera.left = -d;
// this.object.shadow.camera.right = d;
// this.object.shadow.camera.top = d;
// this.object.shadow.camera.bottom = -d;
// this.object.shadow.bias = -0.0001;
// this.object.target = controls.getObject();
// threeworld.scene.add(this.object);
// this.stars = [];
// this.starMaterial = new THREE.MeshBasicMaterial({color : "white", fog: false}) ;
// this.starMaterial.transparent = true;
// this.starMaterial.opacity = 0;
// let sunball = new THREE.Mesh( new THREE.SphereGeometry(100,32,32), new THREE.MeshBasicMaterial({color : "yellow", fog: false}) );
// this.object.add( sunball );
// this.starGyroscope = new THREE.Mesh();
// controls.getObject().add( this.starGyroscope );
// for (let i = 0; i<NBSTARS; i++)
// {
// let radius = AB.randomFloatAtoB ( 5, 20 );
// let star = new THREE.Mesh( new THREE.SphereGeometry(radius,8,8), this.starMaterial);
// let s = AB.randomFloatAtoB ( 0, Math.PI*2 );
// let t = AB.randomFloatAtoB ( 0, Math.PI/2 );
// star.position.set(SKYDISTANCE*Math.cos(s)*Math.sin(t), SKYDISTANCE*Math.cos(t), SKYDISTANCE*Math.sin(s)*Math.sin(t));
// this.stars.push(star);
// this.starGyroscope.add(star);
// }
// //Use this in nextStep to make the sun move
// this.animate = function()
// {
// this.angle+=0.001;
// //normalize angle between -PI and PI
// while (this.angle <= -Math.PI) this.angle += Math.PI*2;
// while (this.angle > Math.PI) this.angle -= Math.PI*2;
// this.object.position.set(controls.getObject().position.x, Math.cos(this.angle)*3000, Math.sin(this.angle)*3000 + controls.getObject().position.z);
// this.object.intensity = this.getSunIntensity();
// let c = new THREE.Color(this.getSkyColor());
// threeworld.scene.background = c;
// threeworld.scene.fog.color = c;
// this.setStarsOpacityAndFog();
// this.starGyroscope.rotation.set(-controls.getObject().rotation.x, -controls.getObject().rotation.y, -controls.getObject().rotation.z);
// }
// //change star opacity and fog depending of the position of the sun
// this.setStarsOpacityAndFog = function()
// {
// if (this.angle > Math.PI/2 && this.angle < Math.PI*3/4)
// {
// soundManager.isNight = true;
// soundManager.playCurrentSound();
// this.starMaterial.opacity = map(this.angle, Math.PI/2, Math.PI*3/4, 0, 0.8);
// threeworld.scene.fog.far = 1000 + SKYDISTANCE * (1 - map(this.angle, Math.PI/2, Math.PI*3/4, 0, 0.8));
// }
// else if (this.angle > -Math.PI*3/4 && this.angle < -Math.PI/2)
// {
// soundManager.isNight = false;
// this.starMaterial.opacity = map(this.angle, -Math.PI*3/4, -Math.PI/2, 0.8, 0);
// threeworld.scene.fog.far = 1000 + SKYDISTANCE * (1 - map(this.angle, -Math.PI*3/4, -Math.PI/2, 0.8, 0));
// }
// }
// //return the color of the sky depending of the position of the sun (to get the sunrise)
// this.getSkyColor = function()
// {
// if (this.angle > -Math.PI*3/8 && this.angle < Math.PI*3/8)
// {
// // console.log("day");
// return 0x7ec0ee;
// }
// else if (this.angle > Math.PI*3/8 && this.angle < Math.PI/2)
// {
// // console.log("Sunset 1");
// return lerpColor(0x7ec0ee, 0xfd5e53, map(this.angle, Math.PI*3/8,Math.PI/2,0,1));
// }
// else if (this.angle > Math.PI/2 && this.angle < Math.PI*5/8)
// {
// // console.log("Sunset 2");
// return lerpColor(0xfd5e53, 0x0c3166, map(this.angle, Math.PI/2,Math.PI*5/8,0,1));
// }
// else if (this.angle > Math.PI*5/8 || this.angle < -Math.PI*3/4)
// {
// // console.log("night");
// return 0x0c3166;
// }
// else if (this.angle > -Math.PI*3/4 && this.angle < -Math.PI/2)
// {
// // console.log("Sunrise 1");
// return lerpColor(0x0c3166, 0xfd5e53, map(this.angle, -Math.PI*3/4,-Math.PI/2,0,1));
// }
// else if (this.angle > -Math.PI/2 && this.angle < -Math.PI*3/8)
// {
// // console.log("Sunrise 2");
// return lerpColor(0xfd5e53, 0x7ec0ee, map(this.angle, -Math.PI/2, -Math.PI*3/8, 0, 1));
// }
// }
// //return intensity of the sun
// this.getSunIntensity = function()
// {
// if (this.angle > -Math.PI*3/8 && this.angle < Math.PI*3/8)
// {
// return 2;
// }
// else if (this.angle > Math.PI*3/8 && this.angle < Math.PI/2)
// {
// return map(this.angle, Math.PI*3/8,Math.PI/2,2,1);
// }
// else if (this.angle > Math.PI/2 && this.angle < Math.PI*3/4)
// {
// return map(this.angle, Math.PI/2,Math.PI*3/4,1,0);
// }
// else if (this.angle > Math.PI*3/4 || this.angle < -Math.PI*3/4)
// {
// return 0;
// }
// else if (this.angle > -Math.PI*3/4 && this.angle < -Math.PI/2)
// {
// return map(this.angle, -Math.PI*3/4,-Math.PI/2,0,1);
// }
// else if (this.angle > -Math.PI/2 && this.angle < -Math.PI*3/8)
// {
// return map(this.angle, -Math.PI/2, -Math.PI*3/8, 1, 2);
// }
// }
// }
//==============================================================================
//==============================================================================
//==============================================================================
// Functions to create/generate infinite world
//==============================================================================
//return a random element of the argument type. If wantRareObject is true, it will return a rare Object
// function getRandomElement(type, wantRareObject)
// {
// if(type === "FOREST")
// {
// if(wantRareObject)
// {
// return objects.objectsForest.rareObjects[AB.randomIntAtoB(0,objects.objectsForest.rareObjects.length - 1)];
// }
// else
// {
// return objects.objectsForest.recurrentObjects[AB.randomIntAtoB(0,objects.objectsForest.recurrentObjects.length - 1)];
// }
// }
// else if(type === "SAND")
// {
// if(wantRareObject)
// {
// return objects.objectsSand.rareObjects[AB.randomIntAtoB(0,objects.objectsSand.rareObjects.length - 1)];
// }
// else
// {
// return objects.objectsSand.recurrentObjects[AB.randomIntAtoB(0,objects.objectsSand.recurrentObjects.length - 1)];
// }
// }
// else if(type === "SNOW")
// {
// if(wantRareObject)
// {
// return objects.objectsSnow.rareObjects[AB.randomIntAtoB(0,objects.objectsSnow.rareObjects.length - 1)];
// }
// else
// {
// return objects.objectsSnow.recurrentObjects[AB.randomIntAtoB(0,objects.objectsSnow.recurrentObjects.length - 1)];
// }
// }
// }
// //Detect what type is in Position x,y. If those coordinates are not
// //in the dimension of the world, it change so that it loop like in the infinite world
// function checkTypeGroundAround(x, y, type)
// {
// if(x < 0) x = worldSize - 1;
// if(y < 0) y = worldSize - 1;
// if(x >= worldSize) x = 0;
// if(y >= worldSize) y = 0;
// return grounds[x][y].type == type;
// }
// //Everytime the player move to a ground that is not yet created,
// //it calls this function to create a Ground in a specific position pos.
// //x and y are for the coordinates in the array2d grounds.
// //type is to determine the type of the ground.
// //elements is when we load a world that alrdy had a ground with elements at this position.
// function createGround(pos, type, x, y, elements = null)
// {
// let conteneur = new THREE.Mesh();
// conteneur.name = "ground";
// let texture;
// let transitionTexture;
// let numberElement = 0;
// let hasRareObject = (AB.randomIntAtoB(0,20) > 18);
// saving.grounds[x][y].biom = type;
// if(type === "FOREST")
// {
// transitionTexture = transitionTextureForest;
// texture = groundTexture;
// numberElement = AB.randomIntAtoB(0,maxElementsForest);
// }
// else if(type === "SAND")
// {
// transitionTexture = transitionTextureSand;
// texture = sandTexture;
// numberElement = AB.randomIntAtoB(0,maxElementsSand);
// }
// else if(type === "SNOW")
// {
// transitionTexture = transitionTextureSnow;
// texture = snowTexture;
// numberElement = AB.randomIntAtoB(0,maxElementsSnow);
// }
// let gr = new THREE.Mesh (
// new THREE.PlaneGeometry ( squaresize*groundMultiplier, squaresize*groundMultiplier ),
// texture );
// gr.receiveShadow = true;
// gr.rotation.x = (Math.PI / 2) * 3;
// gr.position = pos;
// if(!checkTypeGroundAround(x - 1, y, type))
// {
// let a1 = new THREE.Mesh (
// new THREE.PlaneGeometry ( squaresize*groundMultiplier, squaresize*groundMultiplier/8 ),transitionTexture );
// conteneur.add(a1);
// a1.position.set(-squaresize*groundMultiplier/2 , offsetGround, 0);
// a1.rotation.x = (Math.PI / 2) * 3;
// a1.rotation.z = Math.PI/2;
// a1.receiveShadow = true;
// offsetGround += 0.01;
// a1.name = "ground";
// }
// if(!checkTypeGroundAround(x + 1, y, type))
// {
// let a2 = new THREE.Mesh (
// new THREE.PlaneGeometry ( squaresize*groundMultiplier, squaresize*groundMultiplier/8 ),transitionTexture);
// conteneur.add(a2);
// a2.position.set(squaresize*groundMultiplier/2 , offsetGround, 0);
// a2.rotation.z = Math.PI/2;
// a2.rotation.x = (Math.PI / 2) * 3;
// a2.receiveShadow = true;
// offsetGround += 0.01;
// a2.name = "ground";
// }
// if(!checkTypeGroundAround(x, y - 1, type))
// {
// let a3 = new THREE.Mesh (
// new THREE.PlaneGeometry ( squaresize*groundMultiplier, squaresize*groundMultiplier/8 ), transitionTexture);
// conteneur.add(a3);
// a3.position.set(0 , offsetGround, -squaresize*groundMultiplier/2);
// a3.rotation.x = (Math.PI / 2) * 3;
// a3.receiveShadow = true;
// offsetGround += 0.01;
// a3.name = "ground";
// }
// if(!checkTypeGroundAround(x, y + 1, type))
// {
// let a4 = new THREE.Mesh (
// new THREE.PlaneGeometry ( squaresize*groundMultiplier, squaresize*groundMultiplier/8 ), transitionTexture);
// conteneur.add(a4);
// a4.position.set(0, offsetGround , squaresize*groundMultiplier/2);
// a4.rotation.x = (Math.PI / 2) * 3;
// a4.receiveShadow = true;
// offsetGround += 0.01;
// a4.name = "ground";
// }
// if(offsetGround > 0.2)
// {
// offsetGround = 0.001;
// }
// gr.add(conteneur);
// conteneur.rotation.x = -(Math.PI / 2) * 3;
// if(elements == null)
// {
// //add all elements to a group,
// let placeAvailables = [];
// let tmp = [];
// for (let i = 0; i < groundMultiplier; i++)
// {
// tmp[i] = [];
// for (let j = 0; j < groundMultiplier; j++)
// {
// tmp[i][j] = false;
// }
// }
// let numberOfTry = 0;
// while(numberElement > 0 && numberOfTry != 500)
// {
// let randomX = AB.randomIntAtoB(0,groundMultiplier-1);
// let randomY = AB.randomIntAtoB(0,groundMultiplier-1);
// let wasPosed = false;
// while(!wasPosed && numberOfTry != 500)
// {
// numberOfTry++;
// if(tmp[randomX][randomY] === false)
// {
// let t = getRandomElement(type, hasRareObject);
// let randomScale = AB.randomFloatAtoB(0.5,1.5);
// if(t != null)
// {
// let canPoseObject = true;
// for(let i = randomX - Math.ceil(((t.sizeX * randomScale)-1)/2); i <= randomX + Math.ceil(((t.sizeX* randomScale)-1)/2); i++)
// {
// for(let j = randomY - Math.ceil(((t.sizeZ* randomScale)-1)/2); j <= randomY + Math.ceil(((t.sizeZ* randomScale)-1)/2); j++)
// {
// if(i >= 0 && j >= 0 && i < groundMultiplier && j < groundMultiplier)
// {
// if(tmp[i][j])
// {
// canPoseObject = false;
// break;
// }
// }
// else
// {
// canPoseObject = false;
// break;
// }
// }
// }
// if(canPoseObject)
// {
// let obj = t.obj.clone();
// if(!hasRareObject) obj.rotation.y = AB.randomIntAtoB(0,360);
// obj.scale.multiplyScalar(randomScale);
// obj.position.set((randomX - parseInt(groundMultiplier/2)) * squaresize, t.sizeY* randomScale, (randomY - parseInt(groundMultiplier/2)) * squaresize);
// conteneur.add(obj);
// for(let i = randomX - Math.ceil(((t.sizeX* randomScale)-1)/2); i <= randomX + Math.ceil(((t.sizeX* randomScale)-1)/2); i++)
// {
// for(let j = randomY - Math.ceil(((t.sizeZ* randomScale)-1)/2); j <= randomY + Math.ceil(((t.sizeZ* randomScale)-1)/2); j++)
// {
// if(i >= 0 && j >= 0 && i < groundMultiplier && j < groundMultiplier)
// {
// tmp[i][j] = true;
// }
// }
// }
// if(hasRareObject)
// {
// hasRareObject = false;
// }
// let o =
// {
// s: Number((randomScale).toFixed(1)),
// x: Number(((randomX - parseInt(groundMultiplier/2)) * squaresize).toFixed(1)),
// y: Number((t.sizeY* randomScale).toFixed(1)),
// z: Number(((randomY - parseInt(groundMultiplier/2)) * squaresize).toFixed(1)),
// o: t.path,
// }
// saving.grounds[x][y].elements.push(o);
// wasPosed = true;
// numberElement--;
// numberOfTry = 0;
// }
// else
// {
// randomX = AB.randomIntAtoB(0,groundMultiplier-1);
// randomY = AB.randomIntAtoB(0,groundMultiplier-1);
// }
// }
// else
// {
// if(hasRareObject)
// {
// hasRareObject = false;
// }
// }
// }
// else
// {
// randomX = AB.randomIntAtoB(0,groundMultiplier-1);
// randomY = AB.randomIntAtoB(0,groundMultiplier-1);
// }
// }
// }
// }
// else
// {
// for(let i = 0; i < elements.length; i++)
// {
// let t = findObjectLoad(elements[i].o);
// if(t !== null)
// {
// let obj = t.obj.clone();
// obj.scale.multiplyScalar(elements[i].s);
// obj.position.set(elements[i].x, elements[i].y, elements[i].z);
// conteneur.add(obj);
// }
// }
// }
// gr.name = "ground";
// return gr;
// }
// //With the name of an object, it find the object to recreate it.
// //If it wasn't loaded(code changed) it returns null
// function findObjectLoad(path)
// {
// for(let i = 0; i < allObjects.length; i++)
// {
// if(path == allObjects[i].path) return allObjects[i];
// }
// console.log("The Object", path, "was not find in allObjects array that stock all objects that have been loaded");
// return null;
// }
// //Return the type that is the most present around the current position.
// function getTypeAround(array,x,y)
// {
// let sand = 0;
// let snow = 0;
// let forest = 0;
// if(x - 1 >= 0 && array[x - 1][y] !== null)
// {
// if(array[x - 1][y] == "SAND") sand++;
// if(array[x - 1][y] == "FOREST") forest++;
// if(array[x - 1][y] == "SNOW") snow++;
// }
// if(y - 1 >= 0 && array[x][y - 1] !== null)
// {
// if(array[x][y - 1] == "SAND") sand++;
// if(array[x][y - 1] == "FOREST") forest++;
// if(array[x][y - 1] == "SNOW") snow++;
// }
// if(x + 1 < array.length && array[x + 1][y] !== null)
// {
// if(array[x + 1][y] == "SAND") sand++;
// if(array[x + 1][y] == "FOREST") forest++;
// if(array[x + 1][y] == "SNOW") snow++;
// }
// if(y + 1 < array.length && array[x][y + 1] !== null)
// {
// if(array[x][y + 1] == "SAND") sand++;
// if(array[x][y + 1] == "FOREST") forest++;
// if(array[x][y + 1] == "SNOW") snow++;
// }
// if(sand == 0 && snow == 0 && forest == 0)
// {
// return null;
// }
// else if(sand > forest && sand > snow && enableSand)
// {
// return "SAND";
// }
// else if(snow > forest && snow > sand && enableSnow)
// {
// return "SNOW";
// }
// else if(forest > snow && forest > sand && enableForest)
// {
// return "FOREST";
// }
// else
// {
// return null;
// }
// }
// //initialize the ground of the world, to determine all type nd create fake grounds
// //around the world to fake a loop
// function initGround()
// {
// let tmp = new Array(worldSize);
// for (let i = 0; i < worldSize; i++)
// {
// tmp[i] = new Array(worldSize);
// for (let j = 0; j < worldSize; j++)
// {
// tmp[i][j] = null;
// }
// }
// for(let i = 0; i < worldSize; i++)
// {
// for(let j = 0; j < worldSize; j++)
// {
// let typeAround = getTypeAround(tmp,i,j);
// let rand = AB.randomIntAtoB(0,5);
// if(rand < 3 && typeAround !== null)
// {
// tmp[i][j] = typeAround;
// }
// else
// {
// let t = TYPEGROUND[AB.randomIntAtoB(0,TYPEGROUND.length-1)];
// while(!((t == "FOREST" && enableForest) || (t == "SAND" && enableSand) || (t == "SNOW" && enableSnow)))
// {
// t = TYPEGROUND[AB.randomIntAtoB(0,TYPEGROUND.length-1)];
// }
// tmp[i][j] = t;
// }
// }
// }
// for(let i = 0; i < worldSize; i++)
// {
// for(let j = 0; j < worldSize; j++)
// {
// grounds[i][j] = new Ground(false, new THREE.Vector3(0,0,0));
// grounds[i][j].type = tmp[i][j];
// grounds[i][j].active = false;
// saving.grounds[i][j].biom = tmp[i][j];
// }
// }
// for(let i = 0; i < worldSize; i++)
// {
// for(let j = 0; j < worldSize; j++)
// {
// if(i < viewDistance + 1 || i >= worldSize - viewDistance || j >= worldSize - viewDistance || j < viewDistance + 1)
// {
// grounds[i][j].ground = createGround(new THREE.Vector3(0,0,0), grounds[i][j].type, i, j);
// grounds[i][j].ground.position.set((i- Math.trunc(worldSize/2)) * squaresize * groundMultiplier,0, (j- Math.trunc(worldSize/2)) * squaresize*groundMultiplier)
// }
// }
// }
// for(let i = - viewDistance; i < worldSize + viewDistance; i++)
// {
// for(let j = - viewDistance; j < worldSize + viewDistance; j++)
// {
// let b = (worldSize + viewDistance);
// if(i < 0 || j < 0 || i >= worldSize || j >= worldSize)
// {
// let tmp;
// if( i < 0)
// {
// if(j < 0)
// {
// tmp = grounds[worldSize + i][worldSize + j].ground.clone();
// }
// else if(j >= worldSize)
// {
// tmp = grounds[worldSize + i][j - worldSize].ground.clone();
// }
// else
// {
// tmp = grounds[worldSize + i][j].ground.clone();
// }
// }
// else if(i >= worldSize)
// {
// if(j < 0)
// {
// tmp = grounds[i - worldSize][worldSize + j].ground.clone();
// }
// else if(j >= worldSize)
// {
// tmp = grounds[i - worldSize][j - worldSize].ground.clone();
// }
// else
// {
// tmp = grounds[i - worldSize][j].ground.clone();
// }
// }
// else if(i >= worldSize)
// {
// if(j < 0)
// {
// tmp = grounds[i - worldSize][worldSize + j].ground.clone();
// }
// else if(j >= worldSize)
// {
// tmp = grounds[i - worldSize][j - worldSize].ground.clone();
// }
// else
// {
// tmp = grounds[i - worldSize][j].ground.clone();
// }
// }
// else if( j < 0)
// {
// tmp = grounds[i][worldSize + j].ground.clone();
// }
// else if(j >= worldSize)
// {
// tmp = grounds[i][j - worldSize].ground.clone();
// }
// tmp.position.set((i - Math.trunc(worldSize/2)) * squaresize * groundMultiplier,0, (j - Math.trunc(worldSize/2)) * squaresize*groundMultiplier);
// threeworld.scene.add(tmp);
// }
// }
// }
// }
// //This function is called each time the player moves to another ground to check if
// //there is a need to create a ground depending on the viewDistance
// function updateGround()
// {
// for(let i = ai - viewDistance - 1; i < ai + viewDistance + 2; i++)
// {
// for(let j = aj - viewDistance - 1; j < aj + viewDistance + 2; j++)
// {
// if(!(i < 0 || i >= worldSize || j >= worldSize || j < 0))
// {
// if(i == ai - viewDistance - 1 || j == aj - viewDistance - 1 || i == ai + viewDistance + 1 || j == aj + viewDistance + 1)
// {
// if(grounds[i][j] !== null && grounds[i][j].active)
// {
// grounds[i][j].active = false;
// }
// }
// else
// {
// if(typeof grounds[i][j].ground == 'undefined' || grounds[i][j].ground === null)
// {
// grounds[i][j].ground = createGround(new THREE.Vector3(0,0,0), grounds[i][j].type, i, j);
// grounds[i][j].ground.position.set((i- Math.trunc(worldSize/2)) * squaresize * groundMultiplier,0, (j- Math.trunc(worldSize/2)) * squaresize*groundMultiplier);
// grounds[i][j].active = true;
// threeworld.scene.add(grounds[i][j].ground);
// }
// else if(!grounds[i][j].active)
// {
// grounds[i][j].active = true;
// threeworld.scene.add(grounds[i][j].ground);
// }
// }
// }
// }
// }
// }
// //==============================================================================
// //==============================================================================
// //==============================================================================
// // Functions link to an event
// //==============================================================================
// //Create a new infinite world. First destroy the previous one and then recreate one.
// function createNewInfiniteWorld()
// {
// viewDistance = newviewDistance;
// worldSize = newworldSize;
// groundMultiplier = newGroundMultiplier;
// saving = new SaveWorld(worldSize,groundMultiplier, viewDistance);
// while (threeworld.scene.children.length)
// {
// threeworld.scene.remove(threeworld.scene.children[0]);
// }
// threeworld.scene.add(controls.getObject());
// threeworld.scene.fog = new THREE.Fog(SKYCOLOR, 0, SKYDISTANCE);
// // LIGHTS
// let hemiLight = new THREE.HemisphereLight( SKYCOLOR, SKYCOLOR, 0.4 );
// hemiLight.position.set( 0, 50, 0 );
// threeworld.scene.add( hemiLight );
// init();
// }
// function onDocumentTouchStart( event )
// {
// console.log("onDocumentTouchStart");
// event.preventDefault();
// event.clientX = event.touches[0].clientX;
// event.clientY = event.touches[0].clientY;
// onDocumentMouseDown( event );
// }
// //Called when a key is up
// function handleKeyUp (e)
// {
// if((e.keyCode == 38) || (e.keyCode == 40))
// {
// velocity = 0;
// }
// if(e.keyCode == 37 || e.keyCode == 39)
// {
// speedRotation = 0;
// }
// if(e.keyCode == 37 || e.keyCode == 39)
// {
// speedRotation = 0;
// }
// }
// //Called on scrool of the wheel's mouse
// function onScroll(e)
// {
// if(controls.getAttachedObject().children.length !== 0)
// {
// controls.getAttachedObject().remove(controls.getAttachedObject().children[1]);
// controls.getAttachedObject().remove(controls.getAttachedObject().children[0]);
// let delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
// if(delta == 1 && indexObjects + 1 < allObjects.length)
// {
// indexObjects++;
// }
// else if(delta == 1)
// {
// indexObjects = 0;
// }
// else if(delta == -1 && indexObjects - 1 >= 0)
// {
// indexObjects--;
// }
// else if(delta == -1)
// {
// indexObjects = allObjects.length-1;
// }
// let t = allObjects[indexObjects];
// let o = t.obj.clone();
// let bbox = getBoundingBoxObject(o, 0x008000);
// controls.getAttachedObject().add(bbox);
// controls.getAttachedObject().add(o);
// o.position.y = t.sizeY;
// }
// }
// function OnClick(e)
// {
// if(editMode !== null)
// {
// if(editMode === 0)
// {
// selectionObject = null;
// CreateObject(e);
// }
// else if(editMode == 1)
// {
// if(controls.getAttachedObject().children.length != 0)
// {
// controls.getAttachedObject().remove(controls.getAttachedObject().children[1]);
// controls.getAttachedObject().remove(controls.getAttachedObject().children[0]);
// }
// if(e != null && e.which == 3)
// {
// editMode = null;
// }
// if(selectionObject !== null)
// {
// removeObject(threeworld.scene, selectionObject);
// while (selectionBox.children.length)
// {
// selectionBox.remove(selectionBox.children[0]);
// }
// }
// }
// }
// }
// function DestroyObject(e)
// {
// if(e.type !== 'click')
// {
// rayToDestroy = new THREE.Raycaster( controls.getObject().position, threeworld.camera.getWorldDirection(), 0, 800);
// let inter = rayToDestroy.intersectObjects(threeworld.scene.children, true);
// if(inter.length > 0)
// {
// let i = 0;
// while(i < inter.length && (inter[i].object.name == "ground" || inter[i].object == selectionBox)) i++;
// if(i < inter.length && inter[i].object != selectionObject)
// {
// let o = getParent(inter[0].object);
// if(selectionObject != o && o != selectionBox)
// {
// while (selectionBox.children.length)
// {
// selectionBox.remove(selectionBox.children[0]);
// }
// let bbox = getBoundingBoxObject(o, 0xFF0000);
// selectionBox.add(bbox);
// bbox.position.x = o.getWorldPosition().x;
// bbox.position.z = o.getWorldPosition().z;
// selectionObject = o;
// }
// }
// }
// }
// }
// function removeObject(objConteneur, objToDestroy)
// {
// for(let i = 0; i < objConteneur.children.length; i++)
// {
// if(objConteneur.children[i] == objToDestroy)
// {
// objConteneur.remove(objToDestroy);
// }
// else
// {
// removeObject(objConteneur.children[i], objToDestroy);
// }
// }
// }
// //Called when you click left with the nosue after having entered the edit mode with a left click.
// function CreateObject(e = null)
// {
// editMode = 0;
// if(e != null && e.which == 3 && controls.getAttachedObject().children.length !== 0)
// {
// controls.getAttachedObject().remove(controls.getAttachedObject().children[1]);
// controls.getAttachedObject().remove(controls.getAttachedObject().children[0]);
// editMode = null;
// }
// else if(e != null && e.which == 3)
// {
// //TODO Maybe ?
// }
// else
// {
// if(controls.getAttachedObject().children.length !== 0)
// {
// let o = controls.getAttachedObject().children[1].clone();
// userObjects.push(o);
// threeworld.scene.add(o);
// let pos = controls.getAttachedObject().children[1].getWorldPosition();
// let rot = controls.getAttachedObject().children[1].getWorldRotation();
// o.rotation.set();
// o.position.set(pos.x, pos.y, pos.z);
// o.rotation.set(rot.x, rot.y, rot.z);
// let t = allObjects[indexObjects];
// let s =
// {
// s: 1,
// x: Number((pos.x).toFixed(1)),
// y: Number((pos.y).toFixed(1)),
// z: Number((pos.z).toFixed(1)),
// o: t.path,
// }
// saving.userObjects.push(s);
// }
// else
// {
// let t = allObjects[indexObjects];
// let o = t.obj.clone();
// let bbox = getBoundingBoxObject(o, 0x008000);
// controls.getAttachedObject().add(bbox);
// controls.getAttachedObject().add(o);
// o.position.y = t.sizeY;
// }
// }
// }
// //Fonction that return an cube that determine the bouding box of an object
// function getBoundingBoxObject(object, colorBox)
// {
// let bbox = new THREE.Box3().setFromObject(object);
// let cube = new THREE.Mesh(
// new THREE.BoxGeometry(bbox.size().x,bbox.size().y,bbox.size().z),
// new THREE.MeshBasicMaterial({
// color: colorBox,
// transparent: true,
// opacity: 0.5
// }));
// cube.position.y = bbox.size().y/2 ;
// return cube;
// }
// //Return highest parent in the hierarchy that is not a ground or the scene.
// //Useful for models that were not well designed.
// function getParent(object)
// {
// if(object.parent !== null && object.parent.name != "ground" && object.parent != threeworld.scene)
// {
// return getParent(object.parent);
// }
// return object;
// }
// //==============================================================================
// //==============================================================================
// //==============================================================================
// // Function that load Initialize the world
// //==============================================================================
// //Load all objects3D and textures before initialazing the world
// // function loaderObjects()
// // {
// // soundManager = new SoundManager();
// // // load a sound and set it as the Audio object's buffer
// // let audioLoaderForest = new THREE.AudioLoader(loadingManager);
// // audioLoaderForest.load( SOUNDFOREST, function(buffer) {
// // soundManager.soundForest.setBuffer(buffer);
// // soundManager.soundForest.setLoop(true);
// // soundManager.soundForest.setVolume(0);
// // });
// // let audioLoaderSand = new THREE.AudioLoader(loadingManager);
// // audioLoaderSand.load( SOUNDSAND, function( buffer ) {
// // soundManager.soundSand.setBuffer( buffer );
// // soundManager.soundSand.setLoop( true );
// // soundManager.soundSand.setVolume(0);
// // });
// // let audioLoaderSnow = new THREE.AudioLoader(loadingManager);
// // audioLoaderSnow.load( SOUNDSNOW, function( buffer ) {
// // soundManager.soundSnow.setBuffer( buffer );
// // soundManager.soundSnow.setLoop( true );
// // soundManager.soundSnow.setVolume(0);
// // });
// // let audioLoaderNight = new THREE.AudioLoader(loadingManager);
// // audioLoaderNight.load( SOUNDSNOW, function( buffer ) {
// // soundManager.soundNight.setBuffer( buffer );
// // soundManager.soundNight.setLoop( true );
// // soundManager.soundNight.setVolume(0);
// // });
// let planeTex = THREE.ImageUtils.loadTexture( "/uploads/meak/transitionsnow.png" );
// planeTex.wrapS = planeTex.wrapT = THREE.RepeatWrapping;
// planeTex.repeat.set( 8, 8 );
// transitionTextureSnow = new THREE.MeshPhongMaterial({map: planeTex, transparent: true, dithering: true });
// transitionTextureSnow.wrapAround = true;
// transitionTextureSnow.receiveShadow = true;
// planeTex = THREE.ImageUtils.loadTexture( "/uploads/meak/transitionsand.png" );
// planeTex.wrapS = planeTex.wrapT = THREE.RepeatWrapping;
// planeTex.repeat.set( 8, 8 );
// transitionTextureSand = new THREE.MeshPhongMaterial({map: planeTex, transparent: true, dithering: true });
// transitionTextureSand.wrapAround = true;
// transitionTextureSand.receiveShadow = true;
// planeTex = THREE.ImageUtils.loadTexture( "/uploads/meak/transitiongrass.png" );
// planeTex.wrapS = planeTex.wrapT = THREE.RepeatWrapping;
// planeTex.repeat.set( 8, 8 );
// transitionTextureForest = new THREE.MeshPhongMaterial({map: planeTex, transparent: true, dithering: true });
// transitionTextureForest.wrapAround = true;
// transitionTextureForest.receiveShadow = true;
// planeTex = THREE.ImageUtils.loadTexture( "/uploads/meak/grass.jpg" );
// planeTex.wrapS = planeTex.wrapT = THREE.RepeatWrapping;
// planeTex.repeat.set( 8, 8 );
// groundTexture = new THREE.MeshPhongMaterial({map: planeTex, dithering: true });
// groundTexture.wrapAround = true;
// groundTexture.castShadow = true;
// groundTexture.receiveShadow = true;
// planeTex = THREE.ImageUtils.loadTexture( "/uploads/meak/sand.jpg" );
// planeTex.wrapS = planeTex.wrapT = THREE.RepeatWrapping;
// planeTex.repeat.set( 8, 8 );
// sandTexture = new THREE.MeshPhongMaterial({map: planeTex, dithering: true });
// sandTexture.wrapAround = true;
// sandTexture.castShadow = true;
// sandTexture.receiveShadow = true;
// snowTexture = new THREE.MeshPhongMaterial({map: THREE.ImageUtils.loadTexture( "/uploads/meak/snow.png" ), dithering: true });
// snowTexture.wrapAround = true;
// snowTexture.castShadow = true;
// snowTexture.receiveShadow = true;
// console.log("loading " + Object.keys(ARRAYOBJECTSFOREST).length + " elements ");
// for (let key in ARRAYOBJECTSFOREST)
// {
// let loaderMat = new THREE.MTLLoader(loadingManager);
// let loaderObj = new THREE.OBJLoader(loadingManager);
// loaderMat.setTexturePath(PATHTEXTURES);
// let pathMat = PATHTEXTURES + key + '.mtl';
// let pathObj = PATHTEXTURES + key + '.obj';
// let value = ARRAYOBJECTSFOREST[key];
// let nameObj = key;
// console.log("loading " + pathMat + " and " + pathObj);
// loaderMat.load
// (
// // resource URL
// pathMat,
// // called when resource is loaded
// function (materials)
// {
// materials.preload();
// loaderObj.setMaterials(materials);
// // load a resource
// loaderObj.load
// (
// // resource URL
// pathObj,
// // called when resource is loaded
// function ( object )
// {
// let boundingBox = new THREE.Box3().setFromObject(object);
// object.traverse( function ( child ) {
// if ( child instanceof THREE.Mesh ) {
// child.castShadow = true;
// object.receiveShadow = true;
// }
// } );
// object.position.set(0,0,0);
// let sizeX = Math.abs(boundingBox.min.x)+Math.abs(boundingBox.max.x);
// let sizeY = Math.abs(boundingBox.min.y)+Math.abs(boundingBox.max.y);
// let sizeZ = Math.abs(boundingBox.min.z)+Math.abs(boundingBox.max.z);
// let tmp = new Obj(nameObj, 1 + Math.ceil((value * sizeX / squaresize) * 2),Math.abs(boundingBox.min.y)*value, 1 + Math.ceil((value * sizeZ / squaresize) * 2));
// object.scale.multiplyScalar(value);
// tmp.obj = object;
// if( Math.ceil((sizeZ-1)/2) < limitSizeForRareObjects && Math.ceil((sizeX-1)/2) < limitSizeForRareObjects )
// {
// objects.objectsForest.recurrentObjects.push(tmp);
// }
// else
// {
// objects.objectsForest.rareObjects.push(tmp);
// }
// allObjects.push(tmp);
// }
// );
// }
// );
// }
// console.log("loading " + Object.keys(ARRAYOBJECTSSAND).length + " elements ");
// for (let key in ARRAYOBJECTSSAND)
// {
// let loaderMat = new THREE.MTLLoader(loadingManager);
// let loaderObj = new THREE.OBJLoader(loadingManager);
// loaderMat.setTexturePath(PATHTEXTURES);
// let pathMat = PATHTEXTURES + key + '.mtl';
// let pathObj = PATHTEXTURES + key + '.obj';
// let value = ARRAYOBJECTSSAND[key];
// let nameObj = key;
// console.log("loading " + pathMat + " and " + pathObj);
// loaderMat.load
// (
// // resource URL
// pathMat,
// // called when resource is loaded
// function ( materials )
// {
// materials.preload();
// loaderObj.setMaterials(materials);
// // load a resource
// loaderObj.load
// (
// // resource URL
// pathObj,
// // called when resource is loaded
// function ( object )
// {
// let boundingBox = new THREE.Box3().setFromObject(object);
// object.traverse( function ( child ) {
// if ( child instanceof THREE.Mesh ) {
// child.castShadow = true;
// object.receiveShadow = true;
// }
// } );
// object.position.set(0,0,0);
// let sizeX = Math.abs(boundingBox.min.x)+Math.abs(boundingBox.max.x);
// let sizeY = Math.abs(boundingBox.min.y)+Math.abs(boundingBox.max.y);
// let sizeZ = Math.abs(boundingBox.min.z)+Math.abs(boundingBox.max.z);
// let tmp = new Obj(nameObj, 1 + Math.ceil((value * sizeX / squaresize) * 2),Math.abs(boundingBox.min.y)*value, 1 + Math.ceil((value * sizeZ / squaresize) * 2));
// object.scale.multiplyScalar(value);
// tmp.obj = object;
// if( Math.ceil((sizeZ-1)/2) < limitSizeForRareObjects && Math.ceil((sizeX-1)/2) < limitSizeForRareObjects )
// {
// objects.objectsSand.recurrentObjects.push(tmp);
// }
// else
// {
// objects.objectsSand.rareObjects.push(tmp);
// }
// allObjects.push(tmp);
// }
// );
// }
// );
// }
// console.log("loading " + Object.keys(ARRAYOBJECTSSNOW).length + " elements ");
// for (let key in ARRAYOBJECTSSNOW)
// {
// let loaderMat = new THREE.MTLLoader(loadingManager);
// let loaderObj = new THREE.OBJLoader(loadingManager);
// loaderMat.setTexturePath(PATHTEXTURES);
// let pathMat = PATHTEXTURES + key + '.mtl';
// let pathObj = PATHTEXTURES + key + '.obj';
// let value = ARRAYOBJECTSSNOW[key];
// let nameObj = key;
// console.log("loading " + pathMat + " and " + pathObj);
// loaderMat.load
// (
// // resource URL
// pathMat,
// // called when resource is loaded
// function ( materials )
// {
// materials.preload();
// loaderObj.setMaterials(materials);
// // load a resource
// loaderObj.load
// (
// // resource URL
// pathObj,
// // called when resource is loaded
// function ( object )
// {
// let boundingBox = new THREE.Box3().setFromObject(object);
// object.traverse( function ( child ) {
// if ( child instanceof THREE.Mesh ) {
// child.castShadow = true;
// object.receiveShadow = true;
// }
// } );
// object.position.set(0,0,0);
// let sizeX = Math.abs(boundingBox.min.x)+Math.abs(boundingBox.max.x);
// let sizeY = Math.abs(boundingBox.min.y)+Math.abs(boundingBox.max.y);
// let sizeZ = Math.abs(boundingBox.min.z)+Math.abs(boundingBox.max.z);
// let tmp = new Obj(nameObj, 1 + Math.ceil((value * sizeX / squaresize) * 2),Math.abs(boundingBox.min.y)*value, 1 + Math.ceil((value * sizeZ / squaresize) * 2));
// object.scale.multiplyScalar(value);
// tmp.obj = object;
// if( Math.ceil((sizeZ-1)/2) < limitSizeForRareObjects && Math.ceil((sizeX-1)/2) < limitSizeForRareObjects )
// {
// objects.objectsSnow.recurrentObjects.push(tmp);
// }
// else
// {
// objects.objectsSnow.rareObjects.push(tmp);
// }
// allObjects.push(tmp);
// }
// );
// }
// );
// }
// }
// //Initalization before running the world
// function init()
// {
// grounds = new Array(worldSize);
// for (let i = 0; i < worldSize; i++)
// {
// grounds[i] = new Array(worldSize);
// for (let j = 0; j < worldSize; j++)
// {
// grounds[i][j] = null;
// }
// }
// ai = parseInt(worldSize/2 + camera.getWorldPosition().x/(squaresize*groundMultiplier));
// aj = parseInt(worldSize/2 + camera.getWorldPosition().z/(squaresize*groundMultiplier));
// pai = ai;
// paj = aj;
// initGround();
// updateGround();
// // soundManager.currentSound = grounds[ai][aj].type;
// // soundManager.playCurrentSound();
// threeworld.scene.add(selectionBox);
// }
// //Initialization of the loading Manager. When everything is loaded, create all HUD elements and start to initialize the world
// function initLoadingManager()
// {
// loadingManager = new THREE.LoadingManager();
// AB.loadingScreen();
// loadingManager.onLoad = function () {
// console.log( 'Loading complete!');
// if ( AB.onDesktop() )
// {
// $("#user_span1").html("<p>Use WASD or Arrows to move, mouse to look around and space to jump.</p>"+
// "<p>Tap '1' to enter first edit mode, then click left to create Objects</p>"+
// "<p>You can change the object by scrolling !</p>"+
// "<p>Tap '2' to enter second edit mode, then click left to destroy objects</p>"+
// "<p>click right to cancel each edit mode. (Creation or Destruction)</p>"+
// "<p> If you want to re-generate the world, you can press R !</p>");
// if (AB.runloggedin)
// {
// // Definitely can save, not sure if can restore:
// $("#user_span2").html ( " <button onclick='AB.saveData();' >Save your work</button> " );
// // Check if any data exists, if so make restore button:
// AB.queryDataExists(); // will call World.queryDataExists when done
// }
// else
// {
// $("#user_span2").html( " <p> <b> To save your work, go to the World page and run this \"logged in\". </b> </p> " );
// }
// $("#user_span10").html("<p><b>Click screen to enable mouse controls</b></p>");
// $("#user_span4").html("<p> Size of each parcel of the world (1 to 1000) <input type=\"number\" min=\"1\" max=\"1000\" value=\""+ newGroundMultiplier +"\" class=\"slider\" id=\"groundMultiplierHtml\"></p>");
// document.getElementById("groundMultiplierHtml").onchange = function() {
// newGroundMultiplier = +this.value ;
// console.log("groundMultiplierHtml " + newGroundMultiplier);
// HUDEVENT = true;
// }
// document.getElementById("groundMultiplierHtml").onkeypress = function() {
// newGroundMultiplier = +this.value ;
// console.log("groundMultiplierHtml " + newGroundMultiplier);
// HUDEVENT = true;
// }
// $("#user_span5").html("<p> Size of the world (1 to 50) <input type=\"number\" min=\"1\" max=\"50\" value=\""+ newworldSize +"\" class=\"slider\" id=\"worldSizeHtml\"></p>");
// document.getElementById("worldSizeHtml").onchange = function() {
// newworldSize = +this.value;
// if((newworldSize - 1) /2 < newviewDistance)
// {
// newviewDistance = 0;
// document.getElementById("viewDistanceHtml").value = 0;
// }
// HUDEVENT = true;
// console.log("worldSizeHtml " + newworldSize);
// }
// document.getElementById("worldSizeHtml").onkeypress = function() {
// newworldSize = +this.value;
// if((newworldSize - 1) /2 < newviewDistance)
// {
// newviewDistance = 0;
// document.getElementById("viewDistanceHtml").value = 0;
// }
// HUDEVENT = true;
// console.log("worldSizeHtml " + newworldSize);
// }
// $("#user_span6").html("<p> viewDistance in term of parcel (0 to 10) <input type=\"number\" min=\"0\" max=\"10\" value=\""+ newviewDistance +"\" class=\"slider\" id=\"viewDistanceHtml\"></p>");
// document.getElementById("viewDistanceHtml").onchange = function() {
// if(newworldSize/2 >= +this.value)
// {
// newviewDistance = +this.value ;
// }
// console.log("viewDistanceHtml " + newviewDistance);
// HUDEVENT = true;
// }
// document.getElementById("viewDistanceHtml").onkeypress = function() {
// if(newworldSize/2 >= +this.value)
// {
// newviewDistance = +this.value ;
// }
// console.log("viewDistanceHtml " + newviewDistance);
// HUDEVENT = true;
// }
// $("#user_span7").html("<p>Enable snow <input type=\"checkBox\" id=\"enableSnowHtml\" checked> Max element for one section <input type=\"number\" id=\"maxElementsSnowHtml\" min=\"0\" max=\"300\" value=\"" + maxElementsSnow + "\"></p>");
// document.getElementById("maxElementsSnowHtml").onchange = function() {
// maxElementsSnow = this.value;
// HUDEVENT = true;
// }
// document.getElementById("maxElementsSnowHtml").onkeypress = function() {
// maxElementsSnow = this.value;
// HUDEVENT = true;
// }
// document.getElementById("enableSnowHtml").onchange = function() {
// if(!enableSand && !enableForest)
// {
// this.checked = true;
// }
// else
// {
// enableSnow = !enableSnow;
// }
// this.releasePointerCapture();
// HUDEVENT = true;
// }
// $("#user_span8").html("<p>Enable sand <input type=\"checkBox\" id=\"enableSandHtml\" checked> Max element for one section <input type=\"number\" id=\"maxElementsSandHtml\" min=\"0\" max=\"300\" value=\"" + maxElementsSand + "\"></p>");
// document.getElementById("maxElementsSandHtml").onchange = function() {
// maxElementsSand = this.value;
// HUDEVENT = true;
// }
// document.getElementById("maxElementsSandHtml").onkeypress = function() {
// maxElementsSand = this.value;
// HUDEVENT = true;
// }
// document.getElementById("enableSandHtml").onchange = function() {
// if(!enableSnow && !enableForest)
// {
// this.checked = true;
// }
// else
// {
// enableSand = !enableSand;
// }
// HUDEVENT = true;
// }
// $("#user_span9").html("<p>Enable forest <input type=\"checkBox\" id=\"enableForestHtml\" checked> Max element for one section <input type=\"number\" id=\"maxElementsForestHtml\" min=\"0\" max=\"300\" value=\"" + maxElementsForest + "\"></p>");
// document.getElementById("maxElementsForestHtml").onchange = function() {
// maxElementsForest = this.value;
// HUDEVENT = true;
// }
// document.getElementById("maxElementsForestHtml").onkeypress = function() {
// maxElementsForest = this.value;
// HUDEVENT = true;
// }
// document.getElementById("enableForestHtml").onchange = function() {
// if(!enableSnow && !enableSand)
// {
// this.checked = true;
// }
// else
// {
// enableForest = !enableForest;
// }
// HUDEVENT = true;
// }
// }
// else
// {
// $("#user_span1").html( "<p> <b> This World currently only works on desktop. </b> </p>" );
// }
// loaded = true;
// AB.removeLoading();
// createNewInfiniteWorld();
// // sun = new Sun();
// };
// loadingManager.onProgress = function ( url, itemsLoaded, itemsTotal ) {
// let s = 'Loading file: ' + itemsLoaded + ' of ' + itemsTotal + ' files.';
// $("#user_span1").html( s );
// };
// }
// //==============================================================================
// //==============================================================================
// //==============================================================================
// // Function newRun ,init and endRun
// //==============================================================================
// this.newRun = function()
// {
// camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, SKYDISTANCE );
// threeworld.camera = camera;
// let vector = new THREE.Vector3(0, 0, -1);
// vector = camera.localToWorld(vector);
// vector.sub(camera.position); // Now vector is a unit vector with the same direction as the camera
// rayToDestroy = new THREE.Raycaster( camera.position, vector);
// threeworld.init3d ( 0, 0, SKYCOLOR );
// // can adjust renderer:
// threeworld.renderer.shadowMap.enabled = true;
// threeworld.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
// //Initialize the Object that will contain all possible 3D Objects in the world
// objects = new ObjectsConteneur();
// //position of mouse in the canvas
// mouse = new THREE.Vector2();
// //First person controller
// controls = new THREE.PointerLockControls( camera );
// //Start loading objects
// initLoadingManager();
// loaderObjects();
// //This will handle key presses
// let onKeyDown = function ( event ) {
// switch ( event.keyCode ) {
// case 38: // up
// case 87: // w
// moveForward = true;
// break;
// case 37: // left
// case 65: // a
// moveLeft = true; break;
// case 40: // down
// case 83: // s
// moveBackward = true;
// break;
// case 39: // right
// case 68: // d
// moveRight = true;
// break;
// case 32: // space
// if ( canJump === true || true ) velocity.y += 350;
// canJump = false;
// break;
// case 49:
// case 97: // Create Object (1)
// CreateObject();
// break;
// case 50:
// case 98: // Destroy Object (2)
// editMode = 1;
// break;
// // case 82: //Re-generateTheworld (R)
// // createNewInfiniteWorld();
// // threeworld.scene.add(sun.object);
// // break;
// // }
// };
// let onKeyUp = function ( event ) {
// switch( event.keyCode ) {
// case 38: // up
// case 87: // w
// moveForward = false;
// break;
// case 37: // left
// case 65: // a
// moveLeft = false;
// break;
// case 40: // down
// case 83: // s
// moveBackward = false;
// break;
// case 39: // right
// case 68: // d
// moveRight = false;
// break;
// }
// };
// document.addEventListener('keydown', onKeyDown, false );
// document.addEventListener('keyup', onKeyUp, false );
// document.addEventListener('click', OnClick, false);
// document.addEventListener('mousewheel', onScroll, false);
// document.addEventListener('DOMMouseScroll', onScroll, false);
// document.addEventListener('onmousewheel', onScroll, false);
// raycaster = new THREE.Raycaster( new THREE.Vector3(), new THREE.Vector3( 0, - 1, 0 ), 0, 10 );
// //The following handles pointer locking when clicking the window
// let havePointerLock = 'pointerLockElement' in document || 'mozPointerLockElement' in document || 'webkitPointerLockElement' in document;
// console.log(havePointerLock);
// if ( havePointerLock ) {
// let element = document.body;
// let pointerlockchange = function ( event ) {
// if ( document.pointerLockElement === element || document.mozPointerLockElement === element || document.webkitPointerLockElement === element )
// {
// if(HUDEVENT)
// {
// document.exitPointerLock();
// HUDEVENT = false;
// }
// else
// {
// if(!controls.enabled && controls.getAttachedObject().children.length !== 0)
// {
// controls.getAttachedObject().remove(controls.getAttachedObject().children[1]);
// controls.getAttachedObject().remove(controls.getAttachedObject().children[0]);
// }
// if(!controls.enabled)
// {
// controls.enabled = true;
// $("#user_span10").html("");
// }
// }
// } else
// {
// controls.enabled = false;
// $("#user_span10").html("<p><b>Click screen to enable mouse controls</b></p>");
// }
// };
// let pointerlockerror = function ( event ) {
// console.error("pointerlockerror");
// };
// // Hook pointer lock state change events
// document.addEventListener( 'pointerlockchange', pointerlockchange, false );
// document.addEventListener( 'mozpointerlockchange', pointerlockchange, false );
// document.addEventListener( 'webkitpointerlockchange', pointerlockchange, false );
// document.addEventListener( 'pointerlockerror', pointerlockerror, false );
// document.addEventListener( 'mozpointerlockerror', pointerlockerror, false );
// document.addEventListener( 'webkitpointerlockerror', pointerlockerror, false );
// document.addEventListener( 'click', function ( event ) {
// // Ask the browser to lock the pointer
// element.requestPointerLock = element.requestPointerLock || element.mozRequestPointerLock || element.webkitRequestPointerLock;
// element.requestPointerLock();
// }, false );
// } else {
// $("#user_span1").html('<p>Your browser doesn\'t seem to support Pointer Lock API</p>');
// }
// };
// this.nextStep = function()
// {
// if(!loaded)
// {
// console.warn( 'Charging' );
// }
// else
// {
// //======================================================================
// //This will handle moving the player and the camera
// //======================================================================
// // sun.animate();
// let time = performance.now();
// let delta = ( time - prevTime ) / 1000;
// velocity.x -= velocity.x * 10.0 * delta;
// velocity.z -= velocity.z * 10.0 * delta;
// velocity.y -= 9.8 * 100.0 * delta; // 100.0 = mass
// direction.z = Number( moveForward ) - Number( moveBackward );
// direction.x = Number( moveLeft ) - Number( moveRight );
// direction.normalize(); // this ensures consistent movements in all directions
// if ( moveForward || moveBackward ) velocity.z -= direction.z * 400.0 * MOVESPEED * delta;
// if ( moveLeft || moveRight ) velocity.x -= direction.x * 400.0 * MOVESPEED * delta;
// controls.getObject().translateX( velocity.x * delta );
// controls.getObject().translateY( velocity.y * delta );
// controls.getObject().translateZ( velocity.z * delta );
// if ( controls.getObject().position.y < 10 ) {
// velocity.y = 0;
// controls.getObject().position.y = 10;
// canJump = true;
// }
// prevTime = time;
// //Update the position of the payer in the world so that it can generate ground around the player, depending on the viewDistance
// if(worldSize/2 + camera.getWorldPosition().x/(squaresize*groundMultiplier) < 0)
// {
// ai = -Math.ceil(-(worldSize/2 + camera.getWorldPosition().x/(squaresize*groundMultiplier)));
// }
// else
// {
// ai = Math.trunc(worldSize/2 + camera.getWorldPosition().x/(squaresize*groundMultiplier));
// }
// if(worldSize/2 + camera.getWorldPosition().z/(squaresize*groundMultiplier) < 0)
// {
// aj = -Math.ceil(-(worldSize/2 + camera.getWorldPosition().z/(squaresize*groundMultiplier)));
// }
// else
// {
// aj = Math.trunc(worldSize/2 + camera.getWorldPosition().z/(squaresize*groundMultiplier));
// }
// if(ai < 0)
// {
// controls.getObject().position.x = (worldSize/2) * groundMultiplier * squaresize - 0.01;
// }
// if(ai >= worldSize)
// {
// controls.getObject().position.x = - worldSize/2 * groundMultiplier * squaresize;
// }
// if(aj >= worldSize)
// {
// controls.getObject().position.z = - worldSize/2 * groundMultiplier * squaresize;
// }
// if(aj < 0)
// {
// controls.getObject().position.z = (worldSize/2) * groundMultiplier * squaresize - 0.01;
// }
// // if(ai != pai || aj != paj)
// // {
// // pai = ai;
// // paj = aj;
// // updateGround();
// // if(grounds[ai][aj].type != soundManager.currentSound)
// // {
// // soundManager.currentSound = grounds[ai][aj].type;
// // soundManager.playCurrentSound();
// // }
// }
// ///
// //Update of the sound depending of the actual zone where the player is.
// // soundManager.updateSound();
// }
// };
// this.endRun = function()
// {
// };
// //==============================================================================
// //==============================================================================
// //==============================================================================
// // Functions to store/restore data
// //==============================================================================
// this.restoreData = function ( a ) // process object returned from server
// {
// console.log ( "Restore Data");
// //We store saving data so that the player can update his save
// saving = a;
// //We re-generate the world that was saved
// RecreateInfiniteWorld(a);
// };
// this.queryDataExists = function ( exists )
// {
// if ( exists )
// $("#user_span3").html ( "<p> <button onclick='AB.restoreData();' >Restore your work</button> </p>" );
// };
// this.saveData = function() // defines what object to save to server
// {
// HUDEVENT = true;
// return (saving);
// };
// //Function to recreate a world that was saved on the server.
// //a
// function RecreateInfiniteWorld(data)
// {
// worldSize = data.worldSize;
// groundMultiplier = data.groundMultiplier;
// viewDistance = data.viewDistance;
// while (threeworld.scene.children.length)
// {
// threeworld.scene.remove(threeworld.scene.children[0]);
// }
// threeworld.scene.add(controls.getObject());
// // threeworld.scene.add(sun.object);
// threeworld.scene.fog = new THREE.Fog(SKYCOLOR, 0, SKYDISTANCE);
// // LIGHTS
// let hemiLight = new THREE.HemisphereLight( SKYCOLOR, SKYCOLOR, 0.4 );
// hemiLight.position.set( 0, 50, 0 );
// threeworld.scene.add( hemiLight );
// for(let i = 0; i < worldSize; i++)
// {
// for(let j = 0; j < worldSize; j++)
// {
// grounds[i][j] = new Ground(false, new THREE.Vector3(0,0,0));
// grounds[i][j].type = data.grounds[i][j].biom;
// grounds[i][j].active = false;
// saving.grounds[i][j].biom = data.grounds[i][j].biom;
// }
// }
// for(let i = 0; i < worldSize; i++)
// {
// for(let j = 0; j < worldSize; j++)
// {
// if(data.grounds[i][j].elements.length !== 0)
// {
// grounds[i][j].ground = createGround(new THREE.Vector3(0,0,0), grounds[i][j].type, i, j, data.grounds[i][j].elements);
// grounds[i][j].ground.position.set((i- Math.trunc(worldSize/2)) * squaresize * groundMultiplier,0, (j- Math.trunc(worldSize/2)) * squaresize*groundMultiplier)
// threeworld.scene.add(grounds[i][j].ground);
// }
// }
// }
// for(let i = 0; i < data.userObjects.length; i++)
// {
// let t = findObjectLoad(data.userObjects[i].o);
// if(t !== null)
// {
// let obj = t.obj.clone();
// obj.scale.multiplyScalar(data.userObjects[i].s);
// obj.position.set(data.userObjects[i].x, data.userObjects[i].y, data.userObjects[i].z);
// threeworld.scene.add(obj);
// }
// }
// for(let i = - viewDistance; i < worldSize + viewDistance; i++)
// {
// for(let j = - viewDistance; j < worldSize + viewDistance; j++)
// {
// let b = (worldSize + viewDistance);
// if(i < 0 || j < 0 || i >= worldSize || j >= worldSize)
// {
// let tmp;
// if( i < 0)
// {
// if(j < 0)
// {
// tmp = grounds[worldSize + i][worldSize + j].ground.clone();
// }
// else if(j >= worldSize)
// {
// tmp = grounds[worldSize + i][j - worldSize].ground.clone();
// }
// else
// {
// tmp = grounds[worldSize + i][j].ground.clone();
// }
// }
// else if(i >= worldSize)
// {
// if(j < 0)
// {
// tmp = grounds[i - worldSize][worldSize + j].ground.clone();
// }
// else if(j >= worldSize)
// {
// tmp = grounds[i - worldSize][j - worldSize].ground.clone();
// }
// else
// {
// tmp = grounds[i - worldSize][j].ground.clone();
// }
// }
// else if(i >= worldSize)
// {
// if(j < 0)
// {
// tmp = grounds[i - worldSize][worldSize + j].ground.clone();
// }
// else if(j >= worldSize)
// {
// tmp = grounds[i - worldSize][j - worldSize].ground.clone();
// }
// else
// {
// tmp = grounds[i - worldSize][j].ground.clone();
// }
// }
// else if( j < 0)
// {
// tmp = grounds[i][worldSize + j].ground.clone();
// }
// else if(j >= worldSize)
// {
// tmp = grounds[i][j - worldSize].ground.clone();
// }
// tmp.position.set((i - Math.trunc(worldSize/2)) * squaresize * groundMultiplier,0, (j - Math.trunc(worldSize/2)) * squaresize*groundMultiplier);
// threeworld.scene.add(tmp);
// }
// }
// }
// }
// //==============================================================================
// //==============================================================================
// }