var container, stats, gui, promptSound; var switchCamera, scene, renderer; var roamingCamera, cameraControl; var sunLight; var ambientLight; var goRoaming = false, roamingStatus = false; var tween; var trackCamera = new Map(); var renderCamera; var needSet = true; var curBody = "Galaxy", nextBody = curBody; var saveCur, saveNext; var orbitDraw = new Map(); var clock = new THREE.Clock(); var tick = 0; var cometSet = false; var lastCometX, lastCometY, lastCometZ; var params = { Camera: "Galaxy", }; var calculateParams; var orbitParams; var cometParams; var control; var firstflag = true; var options = { position: new THREE.Vector3(), positionRandomness: .3, velocity: new THREE.Vector3(), velocityRandomness: 3.0, color: 0xfff700, colorRandomness: .2, turbulence: 0., lifetime: .1, size: 10, sizeRandomness: 2 }; var spawnerOptions = { spawnRate: 1500000, horizontalSpeed: .1, verticalSpeed: .1, timeScale: .1, }; $('.progress').progressInitialize(); var progressBar = $('#control'); pre(); $(this).removeAttr('onclick'); progressBar.click(function (e) { e.preventDefault(); progressBar.progressSet(0); pre(); $(this).removeAttr('onclick'); }); function pre() { var manifest = [ "res/callisto/diffuse.jpg", "res/comet/particle2.png", "res/comet/perlin-512.png", "res/deimos/diffuse.jpg", "res/deimos/bump.jpg", "res/dione/diffuse.jpg", "res/earth/diffuse.jpg", "res/earth/bump.jpg", "res/earth/clouds.png", "res/earth/night.png", "res/earth/spec.jpg", "res/effects/flare.jpg", "res/europa/diffuse.jpg", "res/io/diffuse.png", "res/jupiter/clouds.png", "res/jupiter/diffuse.jpg", "res/jupiter/ring.png", "res/loading/splash.png", "res/mars/diffuse.jpg", "res/mars/bump.jpg", "res/mercury/diffuse.jpg", "res/mercury/bump.jpg", "res/moon/diffuse.jpg", "res/moon/bump.jpg", "res/neptune/diffuse.jpg", "res/neptune/ring.png", "res/phobos/diffuse.jpg", "res/phobos/bump.jpg", "res/pluto/diffuse.jpg", "res/saturn/diffuse.png", "res/saturn/bump.png", "res/saturn/clouds.png", "res/saturn/ring.png", "res/skybox/posX.jpg", "res/skybox/posY.jpg", "res/skybox/posZ.jpg", "res/skybox/negX.jpg", "res/skybox/negY.jpg", "res/skybox/negZ.jpg", "res/sol/diffuse.png", "res/titan/diffuse.jpg", "res/uranus/diffuse.jpg", "res/uranus/ring.png", "res/venus/diffuse.jpg", "res/venus/bump.jpg", "res/venus/clouds.jpg", ]; $.preLoad(manifest, { each: function (count) { progressBar.progressSet(count * 2); progressBar.attr({'data-loading': (parseInt(count / manifest.length * 100)).toString() + "%"}); }, all: function () { progressBar.progressSet(100); progressBar.attr({'data-loading': (100).toString() + "%"}); init(); animate(); } }); } function initScene() { scene = new THREE.Scene(); scene.background = new THREE.Color(0x000000); } function initCamera() { roamingCamera = new cameraParameters(3000, 200, "Astronaut"); switchCamera = new cameraParameters(3000, 200, "Sun"); switchCamera.setCamera(); trackCamera["Galaxy"] = new cameraParameters(70000, 200, "Sun"); trackCamera["Galaxy"].theta = 80.0; trackCamera["Galaxy"].phi = 0.0; trackCamera["Comet"] = new cameraParameters(1000, 1000, "Comet"); var planets = ["Sun", "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto"]; for (var i in planets) { trackCamera[planets[i]] = new cameraParameters(3.0 * celestialBodies[planets[i]].radius, 3.0 * celestialBodies[planets[i]].radius, planets[i]); } trackCamera["Ship"] = new cameraParameters(3.0 * celestialBodies["Ship"].radius, 3.0 * celestialBodies["Ship"].radius, "Ship") } function initLight() { // Add light sunLight = new THREE.PointLight(0xFFFFFF, 1.0); sunLight.position.set(0, 0, 0); scene.add(sunLight); ambientLight = new THREE.AmbientLight(0xFFFFFF); ambientLight.intensity = 0; scene.add(ambientLight) // sunLight.castShadow = true; } function drawOrbit(celestialBody) { var radius = celestialBody.orbit.semiMajorAxis; var angle = celestialBody.orbit.inclination / 180.0 * Math.PI; var size = 360 / radius; var orbit = new THREE.Geometry(); var e = celestialBody.orbit.eccentricity; var material = new THREE.LineBasicMaterial({vertexColors: true}); for (var i = 0; i <= radius; i++) { var segment = (i * size) * Math.PI / 180; var r = radius * (1 - e * e) / (1 + e * Math.cos(segment)); orbit.vertices.push(new THREE.Vector3((Math.cos(segment) * r) * Math.cos(angle), (Math.cos(segment) * r) * Math.sin(angle), Math.sin(segment) * r)); var color1 = new THREE.Color(0xffffff); var quad = (radius / 4.0); if (i < quad) { color1.setRGB((0 + (4 * i / radius) * 100) / 255, (50 + (4 * i / radius) * 50) / 255, 100.0 / 255); } else if (i >= quad && i < 2 * quad) { color1.setRGB((100 - (4 * i / radius - 1) * 100) / 255, (100 - (4 * i / radius - 1) * 50) / 255, 100.0 / 255); } else if (i >= 2 * quad && i < 3 * quad) { color1.setRGB((0 + (4 * i / radius - 2) * 100) / 255, (50 + (4 * i / radius - 2) * 50) / 255, 100.0 / 255); } else { color1.setRGB((100 - (4 * i / radius - 3) * 100) / 255, (100 - (4 * i / radius - 3) * 50) / 255, 100.0 / 255); } orbit.colors.push(color1); } return new THREE.Line(orbit, material); } function initRender() { renderer = new THREE.WebGLRenderer({antialias: true, alpha: true, preserveDrawingBuffer: true}); renderer.shadowMap.type = THREE.PCFSoftShadowMap; renderer.setPixelRatio(window.devicePixelRatio); renderer.setSize(window.innerWidth, window.innerHeight); //renderer.shadowMapEnabled = true; //renderer.shadowMapSoft = true; //renderer.shadowMap.enabled = true; //renderer.shadowCameraNear = 3; //renderer.shadowCameraFar = 100; //renderer.shadowMapDarkness = 0.2; //renderer.shadowCameraFov = 50; //renderer.shadowMapBias = 0.0039; //renderer.shadowMapWidth = 1024; //renderer.shadowMapHeight = 1024; } function initObjects() { // Add sky box var skyboxTextureFilenames = [ "res/skybox/posX.jpg", "res/skybox/negX.jpg", "res/skybox/posY.jpg", "res/skybox/negY.jpg", "res/skybox/posZ.jpg", "res/skybox/negZ.jpg"]; var materialArray = []; var skyGeometry = new THREE.CubeGeometry(10000000, 10000000, 10000000); for (var i = 0; i < 6; i++) materialArray.push(new THREE.MeshBasicMaterial({ map: textureLoader.load(skyboxTextureFilenames[i]), side: THREE.BackSide })); var skyBox = new THREE.Mesh(skyGeometry, materialArray); skyBox.rotateX(Math.PI / 2); scene.add(skyBox); var orbits = ["Comet", "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto"]; for (var i in orbits) { orbitDraw[orbits[i]] = drawOrbit(celestialBodies[orbits[i]]); } for (var objKey in celestialBodies) { celestialBodies[objKey].generateObjectsOnScene(scene); } for (var objKey in celestialBodies) { if (celestialBodies[objKey].parent != null) celestialBodies[objKey].parent = celestialBodies[celestialBodies[objKey].parent]; } } function initGui() { var calculate = gui.addFolder('Calculate'); calculateParams = { Sun: true, Comet: false, Mercury: true, Venus: true, Earth: true, Mars: true, Jupiter: true, Saturn: true, Uranus: true, Neptune: true, Pluto: true }; for (var i in calculateParams) calculate.add(calculateParams, i); var orbit = gui.addFolder('Orbit'); orbitParams = { Comet: false, Mercury: false, Venus: false, Earth: false, Mars: false, Jupiter: false, Saturn: false, Uranus: false, Neptune: false, Pluto: false }; var comet = gui.addFolder('CometParameters'); cometParams = { Length: 6000., Size: 15000. }; comet.add(cometParams, "Length", 1000, 100000) .onChange(function () { window.removeEventListener('mousedown', onWindowMouseDown, false); }) .onFinishChange(function () { window.addEventListener('mousedown', onWindowMouseDown, false); }); comet.add(cometParams, "Size", 1000, 100000) .onChange(function () { window.removeEventListener('mousedown', onWindowMouseDown, false); }) .onFinishChange(function () { window.addEventListener('mousedown', onWindowMouseDown, false); }); for (var i in orbitParams) orbit.add(orbitParams, i); gui.add(params, 'Camera', ["Galaxy", "Sun", "Comet", "Ship", "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto"]).onChange(function (val) { nextBody = val; if (nextBody != switchCamera.body || (curBody == "Galaxy" && nextBody == "Sun")) { initTween(); cameraCopy(switchCamera, trackCamera[curBody]); setTween(curBody, nextBody); tween.start(); } }); control = new function () { this.Roam = function () { if (roamingStatus == false) { roamingCamera.camera.position.x = celestialBodies["Astronaut"].objectGroup.position.x; roamingCamera.camera.position.y = celestialBodies["Astronaut"].objectGroup.position.y; roamingCamera.camera.position.z = celestialBodies["Astronaut"].objectGroup.position.z; goRoaming = true; initTween(); if (curBody != "Earth") { saveNext = calculateParams["Earth"]; calculateParams["Earth"] = false; } cameraCopy(switchCamera, trackCamera[curBody]); setTween(curBody, null, celestialBodies["Astronaut"].objectGroup.position.x, celestialBodies["Astronaut"].objectGroup.position.y, celestialBodies["Astronaut"].objectGroup.position.z); tween.start(); } else { cameraControl.dispose(); roamingStatus = false; initTween(); setTween(null, curBody, roamingCamera.camera.position.x, roamingCamera.camera.position.y, roamingCamera.camera.position.z); tween.start(); } }; this.Collision = false; this.Light = 1.0; this.Ambient = 0.4; this.TimeScale = 0.1; this.Screenshot = function () { var dataURL = renderer.domElement.toDataURL(); var newWindow = window.open() var img = newWindow.document.createElement("img"); img.src = dataURL; newWindow.document.body.appendChild(img); } }; gui.add(control, 'Light', 0.0, 2.0) .onChange(function (val) { window.removeEventListener('mousedown', onWindowMouseDown, false); sunLight.intensity = val; }) .onFinishChange(function () { window.addEventListener('mousedown', onWindowMouseDown, false); }); gui.add(control, 'Ambient', 0.0, 1.0) .onChange(function (val) { window.removeEventListener('mousedown', onWindowMouseDown, false); ambientLight.intensity = val; }) .onFinishChange(function () { window.addEventListener('mousedown', onWindowMouseDown, false); }); gui.add(control, 'TimeScale', 0.0, 10.0) .onChange(function (val) { window.removeEventListener('mousedown', onWindowMouseDown, false); globalTime.scale = val; }) .onFinishChange(function () { window.addEventListener('mousedown', onWindowMouseDown, false); }); gui.add(control, "Collision"); gui.add(control, "Roam"); gui.add(control, "Screenshot"); gui.autoPlace = true; } function init() { container = document.getElementById('container'); promptSound = document.getElementById('promptSound'); initCamera(); initScene(); initLight(); initObjects(); initRender(); renderCamera = trackCamera["Galaxy"]; stats = new Stats(); gui = new dat.GUI(); gui.close(); dat.GUI.toggleHide(); window.addEventListener('mousedown', onWindowMouseDown, false); window.addEventListener('mousemove', onWindowMouseMove, false); window.addEventListener('mouseup', onWindowMouseUp, false); window.addEventListener('mousewheel', onMouseWheelChange, false); window.addEventListener('DOMMouseScroll', onMouseWheelChange, false); window.addEventListener('resize', onWindowResize, false); initGui() } function onWindowResize() { windowHalfX = window.innerWidth / 2; windowHalfY = window.innerHeight / 2; if (roamingStatus) cameraControl.handleResize(); renderCamera.aspect = window.innerWidth / window.innerHeight; renderCamera.camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); } function checkCrash() { var cameraPos = roamingCamera.camera.position.clone(); for (var objKey in celestialBodies) { if (celestialBodies[objKey].parent == celestialBodies["Sun"]) { var r = celestialBodies[objKey].radius; var dX = celestialBodies[objKey].getX() - roamingCamera.camera.position.x; var dY = celestialBodies[objKey].getY() - roamingCamera.camera.position.y; var dZ = celestialBodies[objKey].getZ() - roamingCamera.camera.position.z; if (Math.sqrt(dX * dX + dY * dY + dZ * dZ) > 2 * r) continue; var localBodyPos = celestialBodies[objKey].objectGroup.position.clone(); var globalBodyPos = localBodyPos.applyMatrix4(celestialBodies[objKey].objectGroup.matrix); var directVector = globalBodyPos.sub(cameraPos).normalize(); var ray = new THREE.Raycaster(cameraPos, directVector); var collisionResults = ray.intersectObject(celestialBodies[objKey].objectGroup, true); if (collisionResults.length > 0 && collisionResults[0].distance < celestialBodies[objKey].radius + directVector.length()) { return true; } } } return false; } function animate() { requestAnimationFrame(animate); TWEEN.update(); if (roamingStatus) { cameraControl.update(clock.getDelta()); if (control.Collision && checkCrash()) { promptSound.play(); } } render(); stats.update(); } function key_press_h() { gui = new dat.GUI(); gui.open(); initGui() }