//==============================================================================// Explanation Sun Made by Mathias Bazin & Nathan Bonnard//==============================================================================// This world was designed to help you create a sun in you world !// For this, you just have to copy and paste 3 functions (lerpcolor, map and Sun).// Then, instantiate an object with the sun class (var obj = new Sun(...))// Don't forget the parameters of the sun : there are informations// about those in the declaration of the function.// And if you want the sun to move, you need to call obj.animate() in the nextStep function // Enjoy the Sunrise !//==============================================================================//==============================================================================const skycolor ='LightBlue';// sky colorconst objectsize =20;// size of object const startRadius =100;// distance from centre we start the camera atconst maxRadius = startRadius *100;// maximum distance from camera we render things const skycolorObject =new THREE.Color( skycolor.toLowerCase());const SKYDISTANCE =3000;const NBSTARS =100;const floorTextureFile ="/uploads/mathias/grass.jpg"//==============================================================================// Functions//==============================================================================/**
* 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;}//==============================================================================// Sun Class//==============================================================================// Here is the Sun Object. Explanation of parameters :// target (Object3D) : the player, or camera if you are in first person view. The sun need to be relative to a point// size (number): the size of the sun & stars// speed (number): the speed of the rotation of the sun// skyDistance (number): the distance of the sky from the target.functionSun(target, size, speed, skyDistance){this.angle =0;this.object =new THREE.DirectionalLight(0xffffff,0.1);this.object.position.set(0,Math.cos(this.angle)*skyDistance,Math.sin(this.angle)*skyDistance);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;
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(size,32,32),new THREE.MeshBasicMaterial({color :"yellow", fog:false}));this.object.add( sunball );this.starGyroscope =new THREE.Mesh();
target.add(this.starGyroscope);//Create all starsfor(let i =0; i<NBSTARS; i++){
let radius = AB.randomFloatAtoB ( size/25, size/8);
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 movethis.animate =function(){this.angle+=0.001* speed;//normalize angle between -PI and PIwhile(this.angle <=-Math.PI)this.angle +=Math.PI*2;while(this.angle >Math.PI)this.angle -=Math.PI*2;this.object.position.set(target.position.x,Math.cos(this.angle)*skyDistance,Math.sin(this.angle)*skyDistance + target.position.z);this.object.intensity =this.getSunIntensity();
let c =new THREE.Color(this.getSkyColor());
threeworld.scene.background = c;this.setStarsOpacity();this.starGyroscope.rotation.set(-target.rotation.x,-target.rotation.y,-target.rotation.z);}//change star opacity and fog depending of the position of the sunthis.setStarsOpacity =function(){if(this.angle >Math.PI/2&&this.angle <Math.PI*3/4){this.starMaterial.opacity = map(this.angle,Math.PI/2,Math.PI*3/4,0,0.8);}elseif(this.angle >-Math.PI*3/4&&this.angle <-Math.PI/2){this.starMaterial.opacity = 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");return0x7ec0ee;}elseif(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));}elseif(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));}elseif(this.angle >Math.PI*5/8||this.angle <-Math.PI*3/4){// console.log("night");return0x0c3166;}elseif(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));}elseif(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 sunthis.getSunIntensity =function(){if(this.angle >-Math.PI*3/8&&this.angle <Math.PI*3/8){return2;}elseif(this.angle >Math.PI*3/8&&this.angle <Math.PI/2){return map(this.angle,Math.PI*3/8,Math.PI/2,2,1);}elseif(this.angle >Math.PI/2&&this.angle <Math.PI*3/4){return map(this.angle,Math.PI/2,Math.PI*3/4,1,0);}elseif(this.angle >Math.PI*3/4||this.angle <-Math.PI*3/4){return0;}elseif(this.angle >-Math.PI*3/4&&this.angle <-Math.PI/2){return map(this.angle,-Math.PI*3/4,-Math.PI/2,0,1);}elseif(this.angle >-Math.PI/2&&this.angle <-Math.PI*3/8){return map(this.angle,-Math.PI/2,-Math.PI*3/8,1,2);}}}functionWorld(){// the object is a cube (each dimension equal): var shape =new THREE.BoxGeometry( objectsize, objectsize, objectsize );var theobject =new THREE.Mesh( shape );var sun;this.newRun =function(){// start a 3D scene:
threeworld.init3d ( startRadius, maxRadius, skycolorObject );//floorvar floorGeometry =new THREE.PlaneBufferGeometry(20000,20000,1000,1000);
floorGeometry.rotateX(-Math.PI /2);var floorTexture =new THREE.ImageUtils.loadTexture ( floorTextureFile );
floorTexture.minFilter = THREE.LinearFilter;
floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
floorTexture.offset.set(0,0);
floorTexture.repeat.set(40,40);var floor =new THREE.Mesh(floorGeometry,new THREE.MeshBasicMaterial({map : floorTexture}));
floor.position.set(0,-objectsize/2,0);
threeworld.scene.add(floor);// add the object to the scene:
threeworld.scene.add(theobject);//Instantiate sun
sun =newSun(theobject,120,10, SKYDISTANCE);};this.nextStep =function(){
sun.animate();}}