add solar
| @@ -1,4 +1,4 @@ | |||||||
| <iframe src="/pkg/galaxy/?star=fff700&in=fff700&out=fff700&bg=0x000000" allowfullscreen frameborder="0" style="width:100%;height:700px;"></iframe> | <iframe src="/pkg/galaxy/?star=fff700&in=fff700&out=fff700&bg=0x000000" allowfullscreen frameborder="0" style="width:100%;height:600px;"></iframe> | ||||||
| <!-- | <!-- | ||||||
| <iframe src="/pkg/galaxy/" allowfullscreen frameborder="0" style="width:100%;height:700px;"></iframe> | <iframe src="/pkg/galaxy/" allowfullscreen frameborder="0" style="width:100%;height:700px;"></iframe> | ||||||
| --> | --> | ||||||
|   | |||||||
| @@ -1,6 +1,8 @@ | |||||||
| <div class="nasa"> | <div class="nasa"> | ||||||
| <iframe src="https://eyes.nasa.gov/apps/solar-system/#/sun/distance?to=earth" allowfullscreen frameborder="0" style="width:100%;height:700px;"></iframe> | 	<iframe src="https://eyes.nasa.gov/apps/solar-system/#/sun/distance" allowfullscreen frameborder="0" style="width:100%;height:700px;"></iframe> | ||||||
| </div> | </div> | ||||||
|  |  | ||||||
| <!-- | <!-- | ||||||
| https://eyes.nasa.gov/apps/solar-system/#/story/voyager_grand_tour?slide=slide_2 | 	https://eyes.nasa.gov/apps/solar-system/#/story/voyager_grand_tour?slide=slide_2 | ||||||
|  | 	<iframe src="https://eyes.nasa.gov/apps/solar-system/#/sun/distance?to=earth" allowfullscreen frameborder="0" style="width:100%;height:700px;"></iframe> | ||||||
| --> | --> | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								layouts/partials/solar.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | |||||||
|  | <iframe src="/pkg/solar/" allowfullscreen frameborder="0" style="width:100%;height:700px;"></iframe> | ||||||
| @@ -22,3 +22,10 @@ | |||||||
| - [icomoon](https://icomoon.io/app/#/select) | - [icomoon](https://icomoon.io/app/#/select) | ||||||
| - [font-awesome](https://github.com/FortAwesome/Font-Awesome) | - [font-awesome](https://github.com/FortAwesome/Font-Awesome) | ||||||
| - [hotkeys-jp](https://github.com/jaywcjlove/hotkeys-js) | - [hotkeys-jp](https://github.com/jaywcjlove/hotkeys-js) | ||||||
|  | - [particles.js](https://github.com/VincentGarreau/particles.js) | ||||||
|  |  | ||||||
|  | ## ref | ||||||
|  |  | ||||||
|  | - [galaxy](https://github.com/the-halfbloodprince/GalaxyM1199) | ||||||
|  | - [solar-sys](https://github.com/solarcg/SolarSys) | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										7
									
								
								static/css/nasa.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,7 @@ | |||||||
|  | span.story-related-list { | ||||||
|  | 	display: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #story-list{ | ||||||
|  | 	display:none; | ||||||
|  | } | ||||||
| @@ -1 +1 @@ | |||||||
| <!doctype html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>ai/galaxy</title><script defer="defer" src="bundle.4f0abc4a7f1c1822a177.js"></script><link href="main.css" rel="stylesheet"></head><body><canvas class="webgl"></canvas></body></html> | <!doctype html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>ai/galaxy</title><script defer="defer" src="bundle.4c347c94d39def84ca4a.js"></script><link href="main.css" rel="stylesheet"></head><body><canvas class="webgl"></canvas></body></html> | ||||||
							
								
								
									
										175
									
								
								static/pkg/solar/css/solar.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,175 @@ | |||||||
|  | body { | ||||||
|  |     color: #ffffff; | ||||||
|  |     font-family: "Segoe UI", Myriad, Helvetica, Arial, "DejaVu Sans", "Noto Sans CJK SC", "Source Han Sans SC"; | ||||||
|  |     font-size: 20px; | ||||||
|  |     text-align: left; | ||||||
|  |     background-color: #000000; | ||||||
|  |     margin: 0px; | ||||||
|  |     overflow: hidden; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .small { | ||||||
|  |     font-size: 12px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #container { | ||||||
|  |     text-align: center; | ||||||
|  |     width: 100%; | ||||||
|  |     height: 100%; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #info { | ||||||
|  |     text-align: center; | ||||||
|  |     position: absolute; | ||||||
|  |     top: 0px; | ||||||
|  |     width: 100%; | ||||||
|  |     padding: 5px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | h3, p { | ||||||
|  |     margin-top: 5px; | ||||||
|  |     margin-bottom: 5px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | img { | ||||||
|  |     margin-top: 10px; | ||||||
|  |     max-width:100% !important; | ||||||
|  |     height:30% !important; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | a { | ||||||
|  |     color: #ffffff; | ||||||
|  |     outline: none; | ||||||
|  |     text-decoration: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | a:hover, a:focus { | ||||||
|  |     color: #ffffff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .progress { | ||||||
|  |     display: inline-block; | ||||||
|  |     font-size: 18px; | ||||||
|  |     color: #ffffff !important; | ||||||
|  |     text-decoration: none !important; | ||||||
|  |     margin-top: 20px; | ||||||
|  |     padding: 6px 70px; | ||||||
|  |     line-height: 1; | ||||||
|  |     overflow: hidden; | ||||||
|  |     position: relative; | ||||||
|  |  | ||||||
|  |     border-style: solid; | ||||||
|  |     border-width: 1px; | ||||||
|  |     border-color: #ffffff; | ||||||
|  |     border-radius: 15px; | ||||||
|  |  | ||||||
|  |     background-color: transparent; | ||||||
|  |  | ||||||
|  |     transition: box-shadow 0.5s; | ||||||
|  |     -moz-transition: box-shadow 0.5s; | ||||||
|  |     -o-transition: box-shadow 0.5s; | ||||||
|  |     -webkit-transition: box-shadow 0.5s; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .progress:hover, .progress:focus { | ||||||
|  |     box-shadow: 0px 0px 30px #ffffffaa; | ||||||
|  |     transition: box-shadow 0.5s; | ||||||
|  |     -moz-transition: box-shadow 0.5s; | ||||||
|  |     -o-transition: box-shadow 0.5s; | ||||||
|  |     -webkit-transition: box-shadow 0.5s; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .progress.in-progress, | ||||||
|  | .progress.finished { | ||||||
|  |     color: transparent !important; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .progress.in-progress:after, | ||||||
|  | .progress.finished:after { | ||||||
|  |     position: absolute; | ||||||
|  |     z-index: 2; | ||||||
|  |     width: 100%; | ||||||
|  |     height: 100%; | ||||||
|  |     text-align: center; | ||||||
|  |     top: 0; | ||||||
|  |     padding-top: inherit; | ||||||
|  |     color: #000000 !important; | ||||||
|  |     left: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /*	If the .in-progress class is set on the button, show the | ||||||
|  | 	contents of the data-loading attribute on the butotn */ | ||||||
|  |  | ||||||
|  | .progress.in-progress:after { | ||||||
|  |     content: attr(data-loading); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* The same goes for the .finished class */ | ||||||
|  |  | ||||||
|  | .progress.finished:after { | ||||||
|  |     content: attr(data-finished); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* The colorful bar that grows depending on the progress */ | ||||||
|  |  | ||||||
|  | .progress .tz-bar { | ||||||
|  |     background-color: #ffffff; | ||||||
|  |     height: 3px; | ||||||
|  |     bottom: 0; | ||||||
|  |     left: 0; | ||||||
|  |     width: 0; | ||||||
|  |     position: absolute; | ||||||
|  |     z-index: 1; | ||||||
|  |  | ||||||
|  |     border-radius: 0 0 2px 2px; | ||||||
|  |  | ||||||
|  |     -webkit-transition: width 0.5s, height 0.5s; | ||||||
|  |     -moz-transition: width 0.5s, height 0.5s; | ||||||
|  |     transition: width 0.5s, height 0.5s; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* The bar can be either horizontal, or vertical */ | ||||||
|  |  | ||||||
|  | .progress .tz-bar.background-horizontal { | ||||||
|  |     height: 100%; | ||||||
|  |     border-radius: 2px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .progress .tz-bar.background-vertical { | ||||||
|  |     height: 0; | ||||||
|  |     top: 0; | ||||||
|  |     width: 100%; | ||||||
|  |     border-radius: 2px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /*---------------------------- | ||||||
|  | 	Color themes | ||||||
|  | -----------------------------*/ | ||||||
|  |  | ||||||
|  | .progress.red { | ||||||
|  |     background-color: #e6537d; | ||||||
|  |     background-image: -webkit-linear-gradient(top, #e6537d, #df5179); | ||||||
|  |     background-image: -moz-linear-gradient(top, #e6537d, #df5179); | ||||||
|  |     background-image: linear-gradient(top, #e6537d, #df5179); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .progress.red .tz-bar { | ||||||
|  |     background-color: #6876b4; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .progress.green { | ||||||
|  |     background-color: #64c896; | ||||||
|  |     background-image: -webkit-linear-gradient(top, #64c896, #5fbd8e); | ||||||
|  |     background-image: -moz-linear-gradient(top, #64c896, #5fbd8e); | ||||||
|  |     background-image: linear-gradient(top, #64c896, #5fbd8e); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .progress.green .tz-bar { | ||||||
|  |     background-color: #9e81d6; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .key-h { | ||||||
|  |     text-align: left; | ||||||
|  | 				padding:0 10px 10px 10px; | ||||||
|  | } | ||||||
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/images/1.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 110 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/images/2.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 144 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/images/3.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 163 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/images/4.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 236 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/images/5.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 153 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/images/6.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 86 KiB | 
							
								
								
									
										70
									
								
								static/pkg/solar/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,70 @@ | |||||||
|  | <!DOCTYPE html> | ||||||
|  | <html lang="en"> | ||||||
|  | <head> | ||||||
|  |     <title>ai/solar</title> | ||||||
|  |     <meta charset="utf-8"> | ||||||
|  |     <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> | ||||||
|  |     <link rel="stylesheet" type="text/css" href="css/solar.css"> | ||||||
|  | </head> | ||||||
|  | <body> | ||||||
|  | 	<div id="container" > | ||||||
|  | 		<!-- | ||||||
|  | 			<div id="prompt"> | ||||||
|  | 			<img src="res/loading/splash.png" width="60%"/> | ||||||
|  | 			<h3>PALE DOTS</h3> | ||||||
|  | 			<p>A mesmerizing journey around the solar system</p> | ||||||
|  | 			<p class="small">This splash screen comes from screenshots of the project</p> | ||||||
|  | 			<a id="control" href="#" class="progress">Start</a> | ||||||
|  | 			</div> | ||||||
|  | 		--> | ||||||
|  | 	</div> | ||||||
|  |  | ||||||
|  | <div> | ||||||
|  |     <audio id="promptSound" src="res/prompt/ding.wav" /> | ||||||
|  | </div> | ||||||
|  | <div id="info"> | ||||||
|  |  | ||||||
|  |     <!-- Libraries --> | ||||||
|  |     <script src="js/libs/jquery-3.2.1.min.js"></script> | ||||||
|  |     <script src="js/libs/three.min.js"></script> | ||||||
|  |     <script src="js/libs/stats.min.js"></script> | ||||||
|  |     <script src="js/libs/tween.min.js"></script> | ||||||
|  |     <script src="js/renderers/Projector.js"></script> | ||||||
|  |     <script src="js/renderers/CanvasRenderer.js"></script> | ||||||
|  |     <script src="js/libs/OBJLoader.js"></script> | ||||||
|  |     <script src="js/libs/MTLLoader.js"></script> | ||||||
|  |     <script src="js/libs/GPUParticleSystem.js"></script> | ||||||
|  |     <script src="js/libs/FirstPersonControls.js"></script> | ||||||
|  |     <script src="js/index.js"></script> | ||||||
|  |     <!-- Loaders --> | ||||||
|  |     <script>var textureLoader = new THREE.TextureLoader();</script> | ||||||
|  |     <script>var objLoader = new THREE.OBJLoader();</script> | ||||||
|  |     <script>var mtlLoader = new THREE.MTLLoader();</script> | ||||||
|  |     <!-- Shaders --> | ||||||
|  |     <script src="js/shaders.js"></script> | ||||||
|  |     <!-- Global timing --> | ||||||
|  |     <script src="js/time.js"></script> | ||||||
|  |     <!-- Camera parameters --> | ||||||
|  |     <!-- Note: THREE.js camera is not in this script. --> | ||||||
|  |     <!-- This file contains an object for calculating camera position. --> | ||||||
|  |     <script src="js/cameraParameters.js"></script> | ||||||
|  |     <!-- Celestial body abstract --> | ||||||
|  |     <script src="js/CelestialBody.js"></script> | ||||||
|  |     <!-- Orbit function --> | ||||||
|  |     <script src="js/orbit.js"></script> | ||||||
|  |     <!-- Data --> | ||||||
|  |     <script src="js/data.js"></script> | ||||||
|  |     <!-- Data --> | ||||||
|  |     <!-- Planet loader --> | ||||||
|  |     <!-- Animation --> | ||||||
|  |     <script src="js/animation.js"></script> | ||||||
|  |     <!-- Controls --> | ||||||
|  |     <script src="js/control.js"></script> | ||||||
|  |     <script src="js/libs/dat.gui.min.js"></script> | ||||||
|  |     <!-- Initializers --> | ||||||
|  |     <script src="js/main.js"></script> | ||||||
|  | 				<div class="key-h"> | ||||||
|  | 					<button id="key-h" onclick="key_press_h();">h</button> | ||||||
|  | 				</div> | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
							
								
								
									
										407
									
								
								static/pkg/solar/js/CelestialBody.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,407 @@ | |||||||
|  | // Celestial body constructor | ||||||
|  | var CelestialBody = function (obj) { | ||||||
|  |     // Meta | ||||||
|  |     this.name = ""; | ||||||
|  |     // If the planet is the sun | ||||||
|  |     this.star = false; | ||||||
|  |     // Object shape info | ||||||
|  |     this.spherical = true; | ||||||
|  |     this.oblateness = 0.; | ||||||
|  |     this.radius = 1.; | ||||||
|  |     this.isComet = false; | ||||||
|  |     this.particleSystem = null; | ||||||
|  |     // Parent/moon objects | ||||||
|  |     this.parent = null; | ||||||
|  |     this.children = []; | ||||||
|  |     // TODO: Model info, to be implemented | ||||||
|  |     // Orbit parameters | ||||||
|  |     // 周期(恒星)、半长轴、离心率、倾角、升交点黄经、平近点角 (历时原点假设轨道是圆形时的黄经偏移) | ||||||
|  |  | ||||||
|  |     this.position = { | ||||||
|  |         x: 0, y: 0, z: 0, | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     this.obj = { | ||||||
|  |         path: null, objPath: null, mtlPath: null, | ||||||
|  |         scale: 1., angle: 0., x: 0., y: 0., z: 0. | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     this.orbit = { | ||||||
|  |         period: 1., semiMajorAxis: 1., eccentricity: 0., | ||||||
|  |         inclination: 0., ascendingNode: 0., meanLongitude: 0. | ||||||
|  |     }; | ||||||
|  |     // Rotation parameters | ||||||
|  |     // 周期(恒星)、倾角(黄赤夹角)、子午角(自转轴所在的与黄道垂直的平面,即子午面,与xOy平面的夹角)、历时原点角度偏移 | ||||||
|  |     // 注:这里我们使用xOz平面作为黄道面 | ||||||
|  |     this.rotation = { | ||||||
|  |         period: 1., inclination: 1., | ||||||
|  |         meridianAngle: 0., offset: 0. | ||||||
|  |     }; | ||||||
|  |     // 远景时显示光芒的参数设定 | ||||||
|  |     // albedo 为反照率 | ||||||
|  |     // 下面给出一个该把这个光点画多亮的粗略估计(只是用来看的,不是很严谨) | ||||||
|  |     // x > R/k:   (2 - <c, p>/(|c|*|p|)) * R^2 * a * log(k*x0/R) / log(k*x/R) | ||||||
|  |     // else:    0 | ||||||
|  |     // 其中,a是反照率,记号<,>表示内积,|.|是二范数,c是摄像机坐标,p是天体坐标 | ||||||
|  |     // R 是天体半径,x 是距天体的距离,即|c - p|,k 是一个系数 | ||||||
|  |     this.albedo = 1.; | ||||||
|  |     this.shineColor = 0xffffff; | ||||||
|  |     // Material settings | ||||||
|  |     this.material = { | ||||||
|  |         // "phong", "lambert", "basic" | ||||||
|  |         type: "phong", | ||||||
|  |         diffuse: {map: null, color: 0xffffff}, | ||||||
|  |         specular: {map: null, color: 0xffffff, shininess: 25}, | ||||||
|  |         night: {map: null}, | ||||||
|  |         bump: {map: null, height: 10} | ||||||
|  |     }; | ||||||
|  |     // Planet ring definitions | ||||||
|  |     this.ring = { | ||||||
|  |         map: null, | ||||||
|  |         lower: 2000, higher: 6000, | ||||||
|  |         color: 0xffffff, specularColor: 0xffffff, specularPower: 5 | ||||||
|  |     }; | ||||||
|  |     // halo effect | ||||||
|  |     this.halo = { | ||||||
|  |         color: null, | ||||||
|  |         radius: 1. | ||||||
|  |     }; | ||||||
|  |     this.atmosphere = { | ||||||
|  |         cloud: { | ||||||
|  |             map: null, height: 1, speed: 20 | ||||||
|  |         }, | ||||||
|  |         // By wave length | ||||||
|  |         scattering: false, | ||||||
|  |         atmosphereColor: new THREE.Vector3(0.5, 0.7, 0.8), | ||||||
|  |         sunsetColor: new THREE.Vector3(0.8, 0.7, 0.6), | ||||||
|  |         atmosphereStrength: 1.0, | ||||||
|  |         sunsetStrength: 1.0 | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     mergeRecursive(this, obj); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | function mergeRecursive(obj1, obj2) { | ||||||
|  |     for (var p in obj2) { | ||||||
|  |         try { | ||||||
|  |             //Property in destination object set; update its value. | ||||||
|  |             if (obj2[p].constructor == Object) { | ||||||
|  |                 obj1[p] = mergeRecursive(obj1[p], obj2[p]); | ||||||
|  |             } else { | ||||||
|  |                 obj1[p] = obj2[p]; | ||||||
|  |             } | ||||||
|  |         } catch (e) { | ||||||
|  |             //Property in destination object not set; create it and set its value. | ||||||
|  |             obj1[p] = obj2[p]; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return obj1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // lens flare texture | ||||||
|  | CelestialBody.prototype.flareTexture = textureLoader.load("res/effects/flare.jpg"); | ||||||
|  |  | ||||||
|  | // IMPORTANT: This function of the prototype generate the object and put it on | ||||||
|  | // the scene. This is the most most important part in drawing the object. | ||||||
|  | CelestialBody.prototype.generateObjectsOnScene = function (argScene) { | ||||||
|  |     var that = this; | ||||||
|  |     // if(this.spherical) | ||||||
|  |     if (!this.spherical) { | ||||||
|  |         if (this.isComet) { | ||||||
|  |             this.cometPivot = new THREE.Group(); | ||||||
|  |             this.objectGroup = new THREE.Group(); | ||||||
|  |             this.particleSystem = new THREE.GPUParticleSystem({ | ||||||
|  |                 maxParticles: 150000 | ||||||
|  |             }); | ||||||
|  |             this.objectGroup.add(this.particleSystem); | ||||||
|  |             argScene.add(this.objectGroup); | ||||||
|  |         } else { | ||||||
|  |             this.objectGroup = new THREE.Group(); | ||||||
|  |             var onProgress = function (xhr) { | ||||||
|  |                 if (xhr.lengthComputable) { | ||||||
|  |                     var percentComplete = xhr.loaded / xhr.total * 100; | ||||||
|  |                 } | ||||||
|  |             }; | ||||||
|  |             var onError = function (xhr) { | ||||||
|  |             }; | ||||||
|  |             if (that.obj.mtlPath != null) { | ||||||
|  |                 mtlLoader.setPath(that.obj.path); | ||||||
|  |                 mtlLoader.load(that.obj.mtlPath, function (materials) { | ||||||
|  |                     materials.preload(); | ||||||
|  |                     objLoader.setMaterials(materials); | ||||||
|  |                     objLoader.setPath(that.obj.path); | ||||||
|  |                     objLoader.load(that.obj.objPath, function (object) { | ||||||
|  |                         that.objectGroup.add(object); | ||||||
|  |                         var scale = that.obj.scale; | ||||||
|  |                         object.rotateY(that.obj.angle / 180.0 * Math.PI); | ||||||
|  |                         object.scale.set(scale, scale, scale); | ||||||
|  |                         object.translateX(that.obj.x); | ||||||
|  |                         object.translateY(that.obj.y); | ||||||
|  |                         object.translateZ(that.obj.z); | ||||||
|  |                     }, onProgress, onError); | ||||||
|  |                 }); | ||||||
|  |             } else { | ||||||
|  |                 objLoader.setPath(that.obj.path); | ||||||
|  |                 objLoader.load(that.obj.objPath, function (object) { | ||||||
|  |                     object.traverse(function (child) { | ||||||
|  |                         var material = new THREE.MeshLambertMaterial(); | ||||||
|  |                         if (child instanceof THREE.Mesh) { | ||||||
|  |                             child.material = material; | ||||||
|  |                         } | ||||||
|  |                     }); | ||||||
|  |                     that.objectGroup.add(object); | ||||||
|  |                     object.rotateY(that.obj.angle / 180.0 * Math.PI); | ||||||
|  |                     var scale = that.obj.scale; | ||||||
|  |                     object.scale.set(scale, scale, scale); | ||||||
|  |                     object.translateX(that.obj.x); | ||||||
|  |                     object.translateY(that.obj.y); | ||||||
|  |                     object.translateZ(that.obj.z); | ||||||
|  |                 }, onProgress, onError); | ||||||
|  |             } | ||||||
|  |             argScene.add(this.objectGroup); | ||||||
|  |         } | ||||||
|  |     } else { | ||||||
|  |         this.bodySphereGeometry = new THREE.SphereGeometry(this.radius, 64, 64); | ||||||
|  |         // else if(!this.spherical) blablabla... | ||||||
|  |         // The base body sphere material | ||||||
|  |         var sphereMaterial = this.bodySphereMaterial = null; | ||||||
|  |         switch (this.material.type) { | ||||||
|  |             case "basic": | ||||||
|  |                 sphereMaterial = this.bodySphereMaterial | ||||||
|  |                     = new THREE.MeshBasicMaterial({ | ||||||
|  |                     color: new THREE.Color(this.material.diffuse.color) | ||||||
|  |                 }); | ||||||
|  |                 if (this.material.diffuse.map !== null) { | ||||||
|  |                     sphereMaterial.map = textureLoader.load(this.material.diffuse.map); | ||||||
|  |                 } | ||||||
|  |                 break; | ||||||
|  |             case "lambert": | ||||||
|  |                 sphereMaterial = this.bodySphereMaterial | ||||||
|  |                     = new THREE.MeshPhongMaterial({ | ||||||
|  |                     color: new THREE.Color(this.material.diffuse.color), | ||||||
|  |                     specular: new THREE.Color(0x000000), | ||||||
|  |                     shininess: 0, | ||||||
|  |                     bumpScale: this.material.bump.height | ||||||
|  |                 }); | ||||||
|  |                 if (this.material.diffuse.map !== null) { | ||||||
|  |                     sphereMaterial.map = textureLoader.load(this.material.diffuse.map); | ||||||
|  |                 } | ||||||
|  |                 break; | ||||||
|  |             case "phong": | ||||||
|  |             default: | ||||||
|  |                 sphereMaterial = this.bodySphereMaterial | ||||||
|  |                     = new THREE.MeshPhongMaterial({ | ||||||
|  |                     color: new THREE.Color(this.material.diffuse.color), | ||||||
|  |                     specular: new THREE.Color(this.material.specular.color), | ||||||
|  |                     shininess: this.material.specular.shininess, | ||||||
|  |                     bumpScale: this.material.bump.height | ||||||
|  |                 }); | ||||||
|  |                 if (this.material.diffuse.map !== null) { | ||||||
|  |                     sphereMaterial.map = textureLoader.load(this.material.diffuse.map); | ||||||
|  |                 } | ||||||
|  |                 if (this.material.specular.map !== null) { | ||||||
|  |                     sphereMaterial.specularMap = textureLoader.load(this.material.specular.map); | ||||||
|  |                 } | ||||||
|  |                 if (this.material.bump.map !== null) { | ||||||
|  |                     sphereMaterial.bumpMap = textureLoader.load(this.material.bump.map); | ||||||
|  |                 } | ||||||
|  |                 break; | ||||||
|  |         } | ||||||
|  |         this.objectGroup = new THREE.Group(); | ||||||
|  |         // Add the main body part | ||||||
|  |         textureLoader.load(this.material.diffuse.map, function (texture) { | ||||||
|  |             this.bodySphereMaterial = new THREE.MeshPhongMaterial({map: texture}); | ||||||
|  |         }); | ||||||
|  |         this.bodySphereMesh = new THREE.Mesh(this.bodySphereGeometry, this.bodySphereMaterial); | ||||||
|  |         this.bodySphereMesh.scale.set(1, 1 - this.oblateness, 1); | ||||||
|  |  | ||||||
|  |         // Add lens flare | ||||||
|  |         this.lensFlare = null; | ||||||
|  |         if (this.star) { | ||||||
|  |             this.lensFlare = | ||||||
|  |                 new THREE.LensFlare(this.flareTexture, 200, | ||||||
|  |                     0, THREE.AdditiveBlending, new THREE.Color(this.shineColor)); | ||||||
|  |             this.lensFlare.position.set(this.getX(), this.getY(), this.getZ()); | ||||||
|  |  | ||||||
|  |             var that = this; | ||||||
|  |             this.lensFlare.customUpdateCallback = function () { | ||||||
|  |                 var cameraDistance = Math.sqrt( | ||||||
|  |                     (trackCamera[params.Camera].getX() - that.getX()) | ||||||
|  |                     * (trackCamera[params.Camera].getX() - that.getX()), | ||||||
|  |                     (trackCamera[params.Camera].getY() - that.getY()) | ||||||
|  |                     * (trackCamera[params.Camera].getY() - that.getY()), | ||||||
|  |                     (trackCamera[params.Camera].getZ() - that.getZ()) | ||||||
|  |                     * (trackCamera[params.Camera].getZ() - that.getZ())); | ||||||
|  |                 this.transparent = 0.3; | ||||||
|  |                 if (cameraDistance < 6000) { | ||||||
|  |                     that.bodySphereMaterial.depthTest = true; | ||||||
|  |                     that.haloMaterial.depthTest = true; | ||||||
|  |                     that.cloudMaterial.depthTest = true; | ||||||
|  |                 } | ||||||
|  |                 else { | ||||||
|  |                     that.bodySphereMaterial.depthTest = false; | ||||||
|  |                     that.haloMaterial.depthTest = false; | ||||||
|  |                 } | ||||||
|  |                 this.updateLensFlares(); | ||||||
|  |             }; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // Add night | ||||||
|  |         this.nightMaterial = null; | ||||||
|  |         this.nightSphereMesh = null; | ||||||
|  |         if (this.material.night.map !== null) { | ||||||
|  |             this.nightMaterial = new THREE.ShaderMaterial({ | ||||||
|  |                 uniforms: { | ||||||
|  |                     nightTexture: {value: textureLoader.load(this.material.night.map)} | ||||||
|  |                 }, | ||||||
|  |                 vertexShader: generalVS, | ||||||
|  |                 fragmentShader: nightFS, | ||||||
|  |                 transparent: true, | ||||||
|  |                 blending: THREE.CustomBlending, | ||||||
|  |                 blendEquation: THREE.AddEquation | ||||||
|  |             }); | ||||||
|  |             this.nightSphereMesh = new THREE.Mesh(this.bodySphereGeometry, this.nightMaterial); | ||||||
|  |             this.objectGroup.add(this.nightSphereMesh); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // Add clouds | ||||||
|  |         this.cloudGeometry = null; | ||||||
|  |         this.cloudMaterial = null; | ||||||
|  |         this.cloudMesh = null; | ||||||
|  |         if (this.atmosphere.cloud.map !== null) { | ||||||
|  |             this.cloudGeometry = new THREE.SphereGeometry(this.radius + this.atmosphere.cloud.height, 64, 64); | ||||||
|  |             if (!this.star) { | ||||||
|  |                 this.cloudMaterial = new THREE.MeshLambertMaterial({ | ||||||
|  |                     map: textureLoader.load(this.atmosphere.cloud.map), | ||||||
|  |                     transparent: true | ||||||
|  |                 }); | ||||||
|  |             } else { | ||||||
|  |                 this.cloudMaterial = new THREE.MeshBasicMaterial({ | ||||||
|  |                     map: textureLoader.load(this.atmosphere.cloud.map), | ||||||
|  |                     transparent: true | ||||||
|  |                 }); | ||||||
|  |             } | ||||||
|  |             this.cloudMesh = new THREE.Mesh(this.cloudGeometry, this.cloudMaterial); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // Add atmosphere | ||||||
|  |         this.atmosphereGeometry = null; | ||||||
|  |         this.atmosphereMaterial = null; | ||||||
|  |         this.atmosphereMesh = null; | ||||||
|  |         if (this.atmosphere.scattering) { | ||||||
|  |             this.atmosphereGeometry = new THREE.SphereGeometry(this.radius * 1.015, 64, 64); | ||||||
|  |             this.atmosphereMaterial = new THREE.ShaderMaterial({ | ||||||
|  |                 uniforms: { | ||||||
|  |                     atmosphereColor: {value: this.atmosphere.atmosphereColor}, | ||||||
|  |                     sunsetColor: {value: this.atmosphere.sunsetColor}, | ||||||
|  |                     atmosphereStrength: {value: this.atmosphere.atmosphereStrength}, | ||||||
|  |                     sunsetStrength: {value: this.atmosphere.sunsetStrength} | ||||||
|  |                 }, | ||||||
|  |                 vertexShader: atmosphereVS, | ||||||
|  |                 fragmentShader: atmosphereFS, | ||||||
|  |                 transparent: true, | ||||||
|  |                 blending: THREE.CustomBlending, | ||||||
|  |                 blendEquation: THREE.AddEquation | ||||||
|  |             }); | ||||||
|  |             this.atmosphereMesh = new THREE.Mesh(this.atmosphereGeometry, this.atmosphereMaterial); | ||||||
|  |             this.objectGroup.add(this.atmosphereMesh); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         this.haloGeometry = null; | ||||||
|  |         this.haloMaterial = null; | ||||||
|  |         this.haloMesh = null; | ||||||
|  |         if (this.halo.color != null) { | ||||||
|  |             this.haloGeometry = new THREE.SphereGeometry(this.halo.radius, 64, 64); | ||||||
|  |             this.haloMaterial = new THREE.ShaderMaterial({ | ||||||
|  |                 uniforms: { | ||||||
|  |                     color: {value: this.halo.color} | ||||||
|  |                 }, | ||||||
|  |                 vertexShader: haloVS, | ||||||
|  |                 fragmentShader: haloFS, | ||||||
|  |                 transparent: true, | ||||||
|  |                 blending: THREE.CustomBlending, | ||||||
|  |                 blendEquation: THREE.AddEquation | ||||||
|  |             }); | ||||||
|  |             this.haloMesh = new THREE.Mesh(this.haloGeometry, this.haloMaterial); | ||||||
|  |             this.objectGroup.add(this.haloMesh); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // Add rings | ||||||
|  |         // Add clouds | ||||||
|  |         this.ringGeometry = null; | ||||||
|  |         this.ringMaterial = null; | ||||||
|  |         this.ringMeshPositive = null; | ||||||
|  |         this.ringMeshNegative = null; | ||||||
|  |         this.ringTexture = null; | ||||||
|  |         if (this.ring.map !== null) { | ||||||
|  |             this.ringTexture = textureLoader.load(this.ring.map); | ||||||
|  |             this.ringTexture.rotation = Math.PI / 2; | ||||||
|  |             this.ringGeometry = new THREE.CylinderGeometry(this.radius + this.ring.lower, this.radius + this.ring.higher, 0, 100, 100, true); | ||||||
|  |             this.ringMaterial = new THREE.MeshPhongMaterial({ | ||||||
|  |                 map: this.ringTexture, transparent: true, | ||||||
|  |                 emissive: new THREE.Color(0x222222) | ||||||
|  |             }); | ||||||
|  |             this.ringMeshPositive = new THREE.Mesh(this.ringGeometry, this.ringMaterial); | ||||||
|  |             this.ringGeometry = new THREE.CylinderGeometry(this.radius + this.ring.higher, this.radius + this.ring.lower, 0, 100, 100, true); | ||||||
|  |             this.ringMeshNegative = new THREE.Mesh(this.ringGeometry, this.ringMaterial); | ||||||
|  |             // if(this.name === "Saturn") { | ||||||
|  |             //     this.ringMeshPositive.castShadow = true; | ||||||
|  |             //     this.ringMeshPositive.receiveShadow = true; | ||||||
|  |             //     this.ringMeshNegative.castShadow = true; | ||||||
|  |             //     this.ringMeshNegative.receiveShadow = true; | ||||||
|  |             //     this.bodySphereMesh.castShadow = true; | ||||||
|  |             //     this.bodySphereMesh.receiveShadow = true; | ||||||
|  |             // } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // Add meshes to the object group | ||||||
|  |         if (this.lensFlare != null) this.objectGroup.add(this.lensFlare); | ||||||
|  |         this.objectGroup.add(this.bodySphereMesh); | ||||||
|  |  | ||||||
|  |         if (this.ringMeshPositive !== null) { | ||||||
|  |             this.objectGroup.add(this.ringMeshPositive); | ||||||
|  |             this.objectGroup.add(this.ringMeshNegative); | ||||||
|  |         } | ||||||
|  |         if (this.cloudMesh !== null) { | ||||||
|  |             this.objectGroup.add(this.cloudMesh); | ||||||
|  |         } | ||||||
|  |         // simple inclination | ||||||
|  |         this.objectGroup.rotateZ(this.rotation.inclination / 180.0 * Math.PI); | ||||||
|  |         argScene.add(this.objectGroup); | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | CelestialBody.prototype.updateClouds = function (time) { | ||||||
|  |     if (this.cloudGeometry !== null) { | ||||||
|  |         this.cloudGeometry.rotateY(this.atmosphere.cloud.speed / 180.0 * Math.PI); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CelestialBody.prototype.update = function (time) { | ||||||
|  |     if (this.objectGroup !== undefined || this.isComet) { | ||||||
|  |         this.updateOrbitAndRotation(time); | ||||||
|  |         if (this.spherical && !this.isComet) | ||||||
|  |             this.updateClouds(time); | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | CelestialBody.prototype.getX = function () { | ||||||
|  |     if (this.objectGroup == null || this.objectGroup.position == null) return 0; | ||||||
|  |     return this.objectGroup.position.getComponent(0); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | CelestialBody.prototype.getY = function () { | ||||||
|  |     if (this.objectGroup == null || this.objectGroup.position == null) return 0; | ||||||
|  |     return this.objectGroup.position.getComponent(1); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | CelestialBody.prototype.getZ = function () { | ||||||
|  |     if (this.objectGroup == null || this.objectGroup.position == null) return 0; | ||||||
|  |     return this.objectGroup.position.getComponent(2); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | CelestialBody.prototype.getRadius = function () { | ||||||
|  |     if (this.objectGroup == null || this.objectGroup.position == null) return 0; | ||||||
|  |     return this.radius; | ||||||
|  | }; | ||||||
							
								
								
									
										79
									
								
								static/pkg/solar/js/Detector.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,79 @@ | |||||||
|  | /** | ||||||
|  |  * @author alteredq / http://alteredqualia.com/ | ||||||
|  |  * @author mr.doob / http://mrdoob.com/ | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | var Detector = { | ||||||
|  |  | ||||||
|  |     canvas: !!window.CanvasRenderingContext2D, | ||||||
|  |     webgl: (function () { | ||||||
|  |  | ||||||
|  |         try { | ||||||
|  |  | ||||||
|  |             var canvas = document.createElement('canvas'); | ||||||
|  |             return !!( window.WebGLRenderingContext && ( canvas.getContext('webgl') || canvas.getContext('experimental-webgl') ) ); | ||||||
|  |  | ||||||
|  |         } catch (e) { | ||||||
|  |  | ||||||
|  |             return false; | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     })(), | ||||||
|  |     workers: !!window.Worker, | ||||||
|  |     fileapi: window.File && window.FileReader && window.FileList && window.Blob, | ||||||
|  |  | ||||||
|  |     getWebGLErrorMessage: function () { | ||||||
|  |  | ||||||
|  |         var element = document.createElement('div'); | ||||||
|  |         element.id = 'webgl-error-message'; | ||||||
|  |         element.style.fontFamily = 'monospace'; | ||||||
|  |         element.style.fontSize = '13px'; | ||||||
|  |         element.style.fontWeight = 'normal'; | ||||||
|  |         element.style.textAlign = 'center'; | ||||||
|  |         element.style.background = '#fff'; | ||||||
|  |         element.style.color = '#000'; | ||||||
|  |         element.style.padding = '1.5em'; | ||||||
|  |         element.style.width = '400px'; | ||||||
|  |         element.style.margin = '5em auto 0'; | ||||||
|  |  | ||||||
|  |         if (!this.webgl) { | ||||||
|  |  | ||||||
|  |             element.innerHTML = window.WebGLRenderingContext ? [ | ||||||
|  |                 'Your graphics card does not seem to support <a href="http://khronos.org/webgl/wiki/Getting_a_WebGL_Implementation" style="color:#000">WebGL</a>.<br />', | ||||||
|  |                 'Find out how to get it <a href="http://get.webgl.org/" style="color:#000">here</a>.' | ||||||
|  |             ].join('\n') : [ | ||||||
|  |                 'Your browser does not seem to support <a href="http://khronos.org/webgl/wiki/Getting_a_WebGL_Implementation" style="color:#000">WebGL</a>.<br/>', | ||||||
|  |                 'Find out how to get it <a href="http://get.webgl.org/" style="color:#000">here</a>.' | ||||||
|  |             ].join('\n'); | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return element; | ||||||
|  |  | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     addGetWebGLMessage: function (parameters) { | ||||||
|  |  | ||||||
|  |         var parent, id, element; | ||||||
|  |  | ||||||
|  |         parameters = parameters || {}; | ||||||
|  |  | ||||||
|  |         parent = parameters.parent !== undefined ? parameters.parent : document.body; | ||||||
|  |         id = parameters.id !== undefined ? parameters.id : 'oldie'; | ||||||
|  |  | ||||||
|  |         element = Detector.getWebGLErrorMessage(); | ||||||
|  |         element.id = id; | ||||||
|  |  | ||||||
|  |         parent.appendChild(element); | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // browserify support | ||||||
|  | if (typeof module === 'object') { | ||||||
|  |  | ||||||
|  |     module.exports = Detector; | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										36
									
								
								static/pkg/solar/js/animation.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,36 @@ | |||||||
|  | function remain(objKey) { | ||||||
|  |     if (celestialBodies[objKey].parent == null) | ||||||
|  |         return true; | ||||||
|  |     if ((calculateParams[celestialBodies[objKey].parent.name] && celestialBodies[objKey].parent.name != "Sun") || | ||||||
|  |         calculateParams[objKey]) | ||||||
|  |         return true; | ||||||
|  |     return false; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function render() { | ||||||
|  |     for (var objKey in celestialBodies) { | ||||||
|  |         if (firstflag || remain(objKey)) { | ||||||
|  |             celestialBodies[objKey].update(globalTime.getRelative()); | ||||||
|  |             if (orbitParams[objKey]) { | ||||||
|  |                 scene.add(orbitDraw[objKey]); | ||||||
|  |             } else { | ||||||
|  |                 scene.remove(orbitDraw[objKey]); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     if (firstflag) { | ||||||
|  |         $(function () { | ||||||
|  |             setTimeout(function () { | ||||||
|  |                 $("#prompt").fadeOut(500); | ||||||
|  |                 container.appendChild(stats.domElement); | ||||||
|  |                 container.appendChild(renderer.domElement); | ||||||
|  |                 gui.open(); | ||||||
|  |             }, 2000); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  |     firstflag = false; | ||||||
|  |     if (needSet) { | ||||||
|  |         renderCamera.setCamera(); | ||||||
|  |     } | ||||||
|  |     renderer.render(scene, renderCamera.camera); | ||||||
|  | } | ||||||
							
								
								
									
										46
									
								
								static/pkg/solar/js/cameraParameters.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,46 @@ | |||||||
|  | var cameraParameters = function (distance, safeDistance, body) { | ||||||
|  |     this.theta = 0.2; | ||||||
|  |     this.phi = 0.3; | ||||||
|  |     this.distance = distance; | ||||||
|  |     this.safeDistance = safeDistance; | ||||||
|  |     this.safeFar = 1e6; | ||||||
|  |     this.body = body; | ||||||
|  |     this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.4, 1e7); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | cameraParameters.prototype.getDistance = function () { | ||||||
|  |     return this.distance; | ||||||
|  | }; | ||||||
|  | cameraParameters.prototype.getCenterX = function () { | ||||||
|  |     if (this.body == "Comet") | ||||||
|  |         return celestialBodies["Comet"].cometPivot.position.getComponent(0); | ||||||
|  |     else | ||||||
|  |         return celestialBodies[this.body].getX(); | ||||||
|  | }; | ||||||
|  | cameraParameters.prototype.getCenterY = function () { | ||||||
|  |     if (this.body == "Comet") | ||||||
|  |         return celestialBodies["Comet"].cometPivot.position.getComponent(1); | ||||||
|  |     else | ||||||
|  |         return celestialBodies[this.body].getY(); | ||||||
|  | }; | ||||||
|  | cameraParameters.prototype.getCenterZ = function () { | ||||||
|  |     if (this.body == "Comet") | ||||||
|  |         return celestialBodies["Comet"].cometPivot.position.getComponent(2); | ||||||
|  |     else | ||||||
|  |         return celestialBodies[this.body].getZ(); | ||||||
|  | }; | ||||||
|  | cameraParameters.prototype.getX = function () { | ||||||
|  |     return this.getCenterX() - (celestialBodies[this.body].getRadius() + this.distance) * Math.cos(this.theta) * Math.cos(this.phi); | ||||||
|  | }; | ||||||
|  | cameraParameters.prototype.getZ = function () { | ||||||
|  |     return this.getCenterZ() - (celestialBodies[this.body].getRadius() + this.distance) * Math.sin(this.theta) * Math.cos(this.phi); | ||||||
|  | }; | ||||||
|  | cameraParameters.prototype.getY = function () { | ||||||
|  |     return this.getCenterY() - (celestialBodies[this.body].getRadius() + this.distance) * Math.sin(this.phi); | ||||||
|  | }; | ||||||
|  | cameraParameters.prototype.setCamera = function () { | ||||||
|  |     this.camera.position.x = this.getX(); | ||||||
|  |     this.camera.position.y = this.getY(); | ||||||
|  |     this.camera.position.z = this.getZ(); | ||||||
|  |     this.camera.lookAt(this.getCenterX(), this.getCenterY(), this.getCenterZ()); | ||||||
|  | }; | ||||||
							
								
								
									
										181
									
								
								static/pkg/solar/js/control.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,181 @@ | |||||||
|  | var windowHalfX = window.innerWidth / 2; | ||||||
|  | var windowHalfY = window.innerHeight / 2; | ||||||
|  |  | ||||||
|  | var mouseStatus = { | ||||||
|  |     x: 0, y: 0, | ||||||
|  |     leftDown: false, centerDown: false, rightDown: false | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | function onWindowMouseMove(event) { | ||||||
|  |     // Keep the value in 0 -- 2 PI | ||||||
|  |     var body = params.Camera; | ||||||
|  |     if (mouseStatus.leftDown) { | ||||||
|  |         trackCamera[body].theta = trackCamera[body].theta % (2 * Math.PI); | ||||||
|  |         trackCamera[body].phi = trackCamera[body].phi % (0.5 * Math.PI); | ||||||
|  |          | ||||||
|  |         trackCamera[body].theta += (event.clientX - windowHalfX - mouseStatus.x) * 0.01; | ||||||
|  |  | ||||||
|  |         if (trackCamera[body].phi - (event.clientY - windowHalfY - mouseStatus.y) * 0.01 >= -0.5 * Math.PI && | ||||||
|  |             trackCamera[body].phi - (event.clientY - windowHalfY - mouseStatus.y) * 0.01 <= 0.5 * Math.PI) | ||||||
|  |             trackCamera[body].phi -= (event.clientY - windowHalfY - mouseStatus.y) * 0.01; | ||||||
|  |     } | ||||||
|  |     mouseStatus.x = event.clientX - windowHalfX; | ||||||
|  |     mouseStatus.y = event.clientY - windowHalfY; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function onWindowMouseDown(event) { | ||||||
|  |     switch (event.which) { | ||||||
|  |         case 1: | ||||||
|  |             mouseStatus.leftDown = true; | ||||||
|  |             break; | ||||||
|  |         case 2: | ||||||
|  |             mouseStatus.centerDown = true; | ||||||
|  |             break; | ||||||
|  |         case 3: | ||||||
|  |         default: | ||||||
|  |             mouseStatus.rightDown = true; | ||||||
|  |             break; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function onWindowMouseUp(event) { | ||||||
|  |     switch (event.which) { | ||||||
|  |         case 1: | ||||||
|  |             mouseStatus.leftDown = false; | ||||||
|  |             break; | ||||||
|  |         case 2: | ||||||
|  |             mouseStatus.centerDown = false; | ||||||
|  |             break; | ||||||
|  |         case 3: | ||||||
|  |         default: | ||||||
|  |             mouseStatus.rightDown = false; | ||||||
|  |             break; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function onMouseWheelChange(event) { | ||||||
|  |     var body = params.Camera; | ||||||
|  |     var delta = Math.max(-1, Math.min(1, (event.wheelDelta || -event.detail))); | ||||||
|  |     var newDistance = trackCamera[body].distance - 0.05 * trackCamera[body].distance * delta; | ||||||
|  |  | ||||||
|  |     if (newDistance <= trackCamera[body].safeDistance) { | ||||||
|  |         newDistance = trackCamera[body].safeDistance; | ||||||
|  |     } else if (newDistance >= trackCamera[body].safeFar) { | ||||||
|  |         newDistance = trackCamera[body].safeFar; | ||||||
|  |     } | ||||||
|  |     trackCamera[body].distance = newDistance; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var posSrc = { pos: 0.0 }; | ||||||
|  | var oX, oY, oZ, dX, dY, dZ, oTheta, dTheta, oPhi, dPhi, oDistance, dDistance, oSafeDis, dSafeDis; | ||||||
|  | var oCX, oCY, oCZ, dCX, dCY, dCZ; | ||||||
|  | tween = new TWEEN.Tween(posSrc) | ||||||
|  |     .to({ pos: 1.0 }, 4000) | ||||||
|  |     .easing(TWEEN.Easing.Quartic.InOut) | ||||||
|  |     .onStart(function () { | ||||||
|  |         globalTimeFlag = false; | ||||||
|  |     }) | ||||||
|  |     .onUpdate(function () { | ||||||
|  |         var pos = posSrc.pos; | ||||||
|  |         switchCamera.camera.position.set(oX + dX * pos, oY + dY * pos, oZ + dZ * pos); | ||||||
|  |         switchCamera.theta = oTheta + dTheta * pos; | ||||||
|  |         switchCamera.phi = oPhi + dPhi * pos; | ||||||
|  |         switchCamera.distance = oDistance + dDistance * pos; | ||||||
|  |         switchCamera.safeDistance = oSafeDis + dSafeDis * pos; | ||||||
|  |         switchCamera.camera.lookAt(oCX + dCX * pos, oCY + dCY * pos, oCZ + dCZ * pos); | ||||||
|  |     }) | ||||||
|  |     .onComplete(function () { | ||||||
|  |         // Need switching to roaming mode | ||||||
|  |         if (goRoaming) { | ||||||
|  |             calculateParams[curBody] = saveCur; | ||||||
|  |             calculateParams["Earth"] = saveNext; | ||||||
|  |             renderCamera = roamingCamera; | ||||||
|  |             cameraControl = new THREE.FirstPersonControls(roamingCamera.camera); | ||||||
|  |             cameraControl.lookSpeed = 0.1; | ||||||
|  |             cameraControl.movementSpeed = 150; | ||||||
|  |             cameraControl.noFly = true; | ||||||
|  |             cameraControl.constrainVertical = true; | ||||||
|  |             cameraControl.verticalMin = 1.0; | ||||||
|  |             cameraControl.verticalMax = 2.0; | ||||||
|  |             cameraControl.lon = -150; | ||||||
|  |             cameraControl.lat = 120; | ||||||
|  |             needSet = false; | ||||||
|  |             roamingStatus = true; | ||||||
|  |             goRoaming = false; | ||||||
|  |             roamingCamera.camera.lookAt(0, 0, 0); | ||||||
|  |         } else { | ||||||
|  |             calculateParams[curBody] = saveCur; | ||||||
|  |             calculateParams[nextBody] = saveNext; | ||||||
|  |             switchCamera.body = nextBody; | ||||||
|  |             curBody = nextBody; | ||||||
|  |             needSet = true; | ||||||
|  |             renderCamera = trackCamera[nextBody]; | ||||||
|  |         } | ||||||
|  |         globalTimeFlag = true; | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  | function initTween() { | ||||||
|  |     saveCur = calculateParams[curBody]; | ||||||
|  |     saveNext = calculateParams[nextBody]; | ||||||
|  |     calculateParams[curBody] = false; | ||||||
|  |     calculateParams[nextBody] = false; | ||||||
|  |     renderCamera = switchCamera; | ||||||
|  |     posSrc.pos = 0.0; | ||||||
|  |     needSet = false; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function setTween(cur, next) { | ||||||
|  |     if (cur == null) { | ||||||
|  |         oX = arguments[2]; | ||||||
|  |         oY = arguments[3]; | ||||||
|  |         oZ = arguments[4]; | ||||||
|  |         oTheta = 0.2; | ||||||
|  |         oPhi = 0.3; | ||||||
|  |         oDistance = 30; | ||||||
|  |         oSafeDis = 30; | ||||||
|  |         oCX = roamingCamera.camera.position.x; | ||||||
|  |         oCY = roamingCamera.camera.position.y; | ||||||
|  |         oCZ = roamingCamera.camera.position.z; | ||||||
|  |     } else { | ||||||
|  |         oX = trackCamera[cur].getX(); | ||||||
|  |         oY = trackCamera[cur].getY(); | ||||||
|  |         oZ = trackCamera[cur].getZ(); | ||||||
|  |         oTheta = trackCamera[cur].theta; | ||||||
|  |         oPhi = trackCamera[cur].phi; | ||||||
|  |         oDistance = trackCamera[cur].distance; | ||||||
|  |         oSafeDis = trackCamera[cur].safeDistance; | ||||||
|  |         oCX = trackCamera[cur].getCenterX(); | ||||||
|  |         oCY = trackCamera[cur].getCenterY(); | ||||||
|  |         oCZ = trackCamera[cur].getCenterZ(); | ||||||
|  |     } | ||||||
|  |     if (next == null) { | ||||||
|  |         dCX = dX = arguments[2] - oX; | ||||||
|  |         dCY = dY = arguments[3] - oY; | ||||||
|  |         dCZ = dZ = arguments[4] - oZ; | ||||||
|  |         dTheta = 0.2 - oTheta; | ||||||
|  |         dPhi = 0.3 - oPhi; | ||||||
|  |         dDistance = 30 - oDistance; | ||||||
|  |         dSafeDis = 30 - oSafeDis; | ||||||
|  |     } else { | ||||||
|  |         dX = trackCamera[next].getX() - oX; | ||||||
|  |         dY = trackCamera[next].getY() - oY; | ||||||
|  |         dZ = trackCamera[next].getZ() - oZ; | ||||||
|  |         dCX = trackCamera[next].getCenterX() - oCX; | ||||||
|  |         dCY = trackCamera[next].getCenterY() - oCY; | ||||||
|  |         dCZ = trackCamera[next].getCenterZ() - oCZ; | ||||||
|  |         dTheta = trackCamera[next].theta - oTheta; | ||||||
|  |         dPhi = trackCamera[next].phi - oPhi; | ||||||
|  |         dDistance = trackCamera[next].distance - oDistance; | ||||||
|  |         dSafeDis = trackCamera[next].safeDistance - oSafeDis; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function cameraCopy(cameraDst, cameraSrc) { | ||||||
|  |     cameraDst.theta = cameraSrc.theta; | ||||||
|  |     cameraDst.phi = cameraSrc.phi; | ||||||
|  |     cameraDst.distance = cameraSrc.distance; | ||||||
|  |     cameraDst.safeDistance = cameraSrc.safeDistance; | ||||||
|  |     cameraDst.body = cameraSrc.body; | ||||||
|  |     cameraDst.setCamera(); | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										547
									
								
								static/pkg/solar/js/data.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,547 @@ | |||||||
|  | celestialBodies = { | ||||||
|  |     Sun: new CelestialBody({ | ||||||
|  |         name: "Sun", | ||||||
|  |         star: true, | ||||||
|  |         parent: "Sun", | ||||||
|  |         radius: 200., | ||||||
|  |         shineColor: 0xfff700, | ||||||
|  |         orbit: { | ||||||
|  |             semiMajorAxis: 0. | ||||||
|  |         }, | ||||||
|  |         rotation: { | ||||||
|  |             period: 2500, | ||||||
|  |             inclination: 0, | ||||||
|  |         }, | ||||||
|  |         material: { | ||||||
|  |             type: "basic", | ||||||
|  |             diffuse: {map: "res/sol/diffuse.png"} | ||||||
|  |         }, | ||||||
|  |         atmosphere: { | ||||||
|  |             cloud: { | ||||||
|  |                 map: "res/sol/overlay.png", | ||||||
|  |                 height: 1, | ||||||
|  |                 speed: 1 | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         halo: { | ||||||
|  |             color: new THREE.Color(0xfff700), | ||||||
|  |             radius: 500. | ||||||
|  |         } | ||||||
|  |     }), | ||||||
|  |     Mercury: new CelestialBody({ | ||||||
|  |         name: "Mercury", | ||||||
|  |         radius: 3.8256, | ||||||
|  |         parent: "Sun", | ||||||
|  |         shineColor: 0x9999ff, | ||||||
|  |         orbit: { | ||||||
|  |             period: 1.204, | ||||||
|  |             semiMajorAxis: 387.1, | ||||||
|  |             eccentricity: 0.2056, | ||||||
|  |             inclination: 7.0049 | ||||||
|  |         }, | ||||||
|  |         rotation: { | ||||||
|  |             period: 1407.509405, | ||||||
|  |             inclination: 28.55, | ||||||
|  |             meridianAngle: 0., | ||||||
|  |             offset: 0. | ||||||
|  |         }, | ||||||
|  |         material: { | ||||||
|  |             type: "lambert", | ||||||
|  |             diffuse: {map: "res/mercury/diffuse.jpg"}, | ||||||
|  |             bump: {map: "res/mercury/bump.jpg", height: 0.} | ||||||
|  |         } | ||||||
|  |     }), | ||||||
|  |     Venus: new CelestialBody({ | ||||||
|  |         name: "Venus", | ||||||
|  |         radius: 9.488, | ||||||
|  |         parent: "Sun", | ||||||
|  |         shineColor: 0x9999ff, | ||||||
|  |         orbit: { | ||||||
|  |             period: 3.076, | ||||||
|  |             semiMajorAxis: 723.3, | ||||||
|  |             eccentricity: 0.0068, | ||||||
|  |             inclination: 3.3947 | ||||||
|  |         }, | ||||||
|  |         rotation: { | ||||||
|  |             period: 5832.443616, | ||||||
|  |             inclination: 157.16, | ||||||
|  |             meridianAngle: 0., | ||||||
|  |             offset: 0. | ||||||
|  |         }, | ||||||
|  |         material: { | ||||||
|  |             type: "lambert", | ||||||
|  |             diffuse: {map: "res/venus/diffuse.jpg"}, | ||||||
|  |             bump: {map: "res/venus/bump.jpg", height: 0.} | ||||||
|  |         }, | ||||||
|  |         atmosphere: { | ||||||
|  |             cloud: { | ||||||
|  |                 map: "res/venus/clouds.jpg", | ||||||
|  |                 height: 0.5, | ||||||
|  |                 speed: 0.02 | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     }), | ||||||
|  |     Earth: new CelestialBody({ | ||||||
|  |         name: "Earth", | ||||||
|  |         radius: 10., | ||||||
|  |         parent: "Sun", | ||||||
|  |         shineColor: 0x6666ff, | ||||||
|  |         orbit: { | ||||||
|  |             period: 5., | ||||||
|  |             semiMajorAxis: 1000., | ||||||
|  |             eccentricity: 0.0167, | ||||||
|  |             inclination: 0.0001 | ||||||
|  |         }, | ||||||
|  |         rotation: { | ||||||
|  |             period: 23.93447117, | ||||||
|  |             inclination: -23.4392911, | ||||||
|  |             meridianAngle: 280.147, | ||||||
|  |             offset: 0. | ||||||
|  |         }, | ||||||
|  |         material: { | ||||||
|  |             type: "phong", | ||||||
|  |             diffuse: {map: "res/earth/diffuse.jpg"}, | ||||||
|  |             specular: {map: "res/earth/spec.jpg", color: 0x243232, shininess: 25}, | ||||||
|  |             bump: {map: "res/earth/bump.jpg", height: 0.05}, | ||||||
|  |             night: {map: "res/earth/night.png"} | ||||||
|  |         }, | ||||||
|  |         atmosphere: { | ||||||
|  |             cloud: { | ||||||
|  |                 map: "res/earth/clouds.png", | ||||||
|  |                 height: 0.1, | ||||||
|  |                 speed: 0.02 | ||||||
|  |             }, | ||||||
|  |             scattering: true, | ||||||
|  |             atmosphereColor: new THREE.Vector3(0.5, 0.7, 0.8), | ||||||
|  |             sunsetColor: new THREE.Vector3(0.8, 0.7, 0.6), | ||||||
|  |             atmosphereStrength: 1.5, | ||||||
|  |             sunsetStrength: 1.0 | ||||||
|  |         } | ||||||
|  |     }), | ||||||
|  |     Comet: new CelestialBody({ | ||||||
|  |         name: "Comet", | ||||||
|  |         parent: "Sun", | ||||||
|  |         radius: 0, | ||||||
|  |         spherical: false, | ||||||
|  |         isComet: true, | ||||||
|  |         orbit: { | ||||||
|  |             period: 3.5, | ||||||
|  |             semiMajorAxis: 3000., | ||||||
|  |             eccentricity: 0.5, | ||||||
|  |             inclination: 10., | ||||||
|  |         }, | ||||||
|  |     }), | ||||||
|  |     Ship: new CelestialBody({ | ||||||
|  |         name: "Ship", | ||||||
|  |         parent: "Earth", | ||||||
|  |         radius: 0.2, | ||||||
|  |         spherical: false, | ||||||
|  |         obj: { | ||||||
|  |             path: "res/space/", | ||||||
|  |             objPath: "tiangong.obj", | ||||||
|  |             mtlPath: "tiangong.mtl", | ||||||
|  |             angle: -30, | ||||||
|  |             scale: 0.008, | ||||||
|  |         }, | ||||||
|  |         orbit: { | ||||||
|  |             period: 1.0, | ||||||
|  |             semiMajorAxis: 15., | ||||||
|  |             inclination: 30, | ||||||
|  |         }, | ||||||
|  |         rotation: { | ||||||
|  |             period: 100.0, | ||||||
|  |             inclination: 0, | ||||||
|  |         }, | ||||||
|  |     }), | ||||||
|  |     Astronaut: new CelestialBody({ | ||||||
|  |         name: "Astronaut", | ||||||
|  |         parent: "Earth", | ||||||
|  |         radius: 0.05, | ||||||
|  |         spherical: false, | ||||||
|  |         obj: { | ||||||
|  |             path: "res/space/", | ||||||
|  |             objPath: "man.obj", | ||||||
|  |             mtlPath: null, | ||||||
|  |             scale: 0.008, | ||||||
|  |             angle: 235, | ||||||
|  |             x: 0.04, | ||||||
|  |             y: 0.02, | ||||||
|  |             z: 0.01, | ||||||
|  |         }, | ||||||
|  |         orbit: { | ||||||
|  |             period: 1.0, | ||||||
|  |             semiMajorAxis: 15., | ||||||
|  |             inclination: 30, | ||||||
|  |         }, | ||||||
|  |         rotation: { | ||||||
|  |             period: 100.0, | ||||||
|  |             inclination: 0, | ||||||
|  |         }, | ||||||
|  |     }), | ||||||
|  |     Moon: new CelestialBody({ | ||||||
|  |         name: "Moon", | ||||||
|  |         radius: 2.7243, | ||||||
|  |         parent: "Earth", | ||||||
|  |         shineColor: 0xff9988, | ||||||
|  |         orbit: { | ||||||
|  |             period: 2.0749, | ||||||
|  |             semiMajorAxis: 25., | ||||||
|  |             eccentricity: 0.0549, | ||||||
|  |             inclination: 5.15 | ||||||
|  |         }, | ||||||
|  |         rotation: { | ||||||
|  |             period: 655.2, | ||||||
|  |             inclination: 23.4608, | ||||||
|  |             meridianAngle: 0., | ||||||
|  |             offset: 0. | ||||||
|  |         }, | ||||||
|  |         material: { | ||||||
|  |             type: "lambert", | ||||||
|  |             diffuse: {map: "res/moon/diffuse.jpg"}, | ||||||
|  |             bump: {map: "res/moon/bump.jpg", height: 0.1} | ||||||
|  |         } | ||||||
|  |     }), | ||||||
|  |     Mars: new CelestialBody({ | ||||||
|  |         name: "Mars", | ||||||
|  |         radius: 5.3226, | ||||||
|  |         parent: "Sun", | ||||||
|  |         shineColor: 0xff9988, | ||||||
|  |         orbit: { | ||||||
|  |             period: 9.4095, | ||||||
|  |             semiMajorAxis: 1523.7, | ||||||
|  |             eccentricity: 0.0934, | ||||||
|  |             inclination: 1.8506 | ||||||
|  |         }, | ||||||
|  |         rotation: { | ||||||
|  |             period: 24.622962156, | ||||||
|  |             inclination: 37.11350, | ||||||
|  |             meridianAngle: 0., | ||||||
|  |             offset: 0. | ||||||
|  |         }, | ||||||
|  |         material: { | ||||||
|  |             type: "lambert", | ||||||
|  |             diffuse: {map: "res/mars/diffuse.jpg"}, | ||||||
|  |             bump: {map: "res/mars/bump.jpg", height: 1.} | ||||||
|  |         }, | ||||||
|  |         atmosphere: { | ||||||
|  |             scattering: true, | ||||||
|  |             atmosphereColor: new THREE.Vector3(0.9, 0.8, 0.6), | ||||||
|  |             sunsetColor: new THREE.Vector3(0.4, 0.5, 0.7), | ||||||
|  |             atmosphereStrength: 1.0, | ||||||
|  |             sunsetStrength: 0.9 | ||||||
|  |         } | ||||||
|  |     }), | ||||||
|  |     Phobos: new CelestialBody({ | ||||||
|  |         name: "Phobos", | ||||||
|  |         radius: 1, | ||||||
|  |         parent: "Mars", | ||||||
|  |         shineColor: 0xff9988, | ||||||
|  |         orbit: { | ||||||
|  |             period: 1.5945, | ||||||
|  |             semiMajorAxis: 20, | ||||||
|  |             eccentricity: 0.0151, | ||||||
|  |             inclination: 1.082 | ||||||
|  |         }, | ||||||
|  |         rotation: { | ||||||
|  |             period: 100., | ||||||
|  |             inclination: 37.10, | ||||||
|  |             meridianAngle: 0., | ||||||
|  |             offset: 0. | ||||||
|  |         }, | ||||||
|  |         material: { | ||||||
|  |             type: "lambert", | ||||||
|  |             diffuse: {map: "res/phobos/diffuse.jpg"}, | ||||||
|  |             bump: {map: "res/phobos/bump.jpg", height: 10.} | ||||||
|  |         } | ||||||
|  |     }), | ||||||
|  |     Deimos: new CelestialBody({ | ||||||
|  |         name: "Deimos", | ||||||
|  |         radius: 0.5, | ||||||
|  |         parent: "Mars", | ||||||
|  |         shineColor: 0xff9988, | ||||||
|  |         orbit: { | ||||||
|  |             period: 6.3122, | ||||||
|  |             semiMajorAxis: 30, | ||||||
|  |             eccentricity: 0.00033, | ||||||
|  |             inclination: 1.791 | ||||||
|  |         }, | ||||||
|  |         rotation: { | ||||||
|  |             period: 150., | ||||||
|  |             inclination: 36.48, | ||||||
|  |             meridianAngle: 0., | ||||||
|  |             offset: 0. | ||||||
|  |         }, | ||||||
|  |         material: { | ||||||
|  |             type: "lambert", | ||||||
|  |             diffuse: {map: "res/deimos/diffuse.jpg"}, | ||||||
|  |             bump: {map: "res/deimos/bump.jpg", height: 10.} | ||||||
|  |         } | ||||||
|  |     }), | ||||||
|  |     Jupiter: new CelestialBody({ | ||||||
|  |         name: "Jupiter", | ||||||
|  |         radius: 112.09, | ||||||
|  |         parent: "Sun", | ||||||
|  |         shineColor: 0x9999ff, | ||||||
|  |         orbit: { | ||||||
|  |             period: 59.3, | ||||||
|  |             semiMajorAxis: 2000., | ||||||
|  |             eccentricity: 0.0484, | ||||||
|  |             inclination: 1.3053 | ||||||
|  |         }, | ||||||
|  |         rotation: { | ||||||
|  |             period: 238.23, | ||||||
|  |             inclination: 2.22, | ||||||
|  |             meridianAngle: 0., | ||||||
|  |             offset: 0. | ||||||
|  |         }, | ||||||
|  |         material: { | ||||||
|  |             type: "lambert", | ||||||
|  |             diffuse: {map: "res/jupiter/diffuse.jpg"}, | ||||||
|  |         }, | ||||||
|  |         atmosphere: { | ||||||
|  |             cloud: { | ||||||
|  |                 map: "res/jupiter/clouds.png", | ||||||
|  |                 height: 0.3, | ||||||
|  |                 speed: 0.02 | ||||||
|  |             }, | ||||||
|  |             scattering: true, | ||||||
|  |             atmosphereColor: new THREE.Vector3(1.0, 0.8, 0.7), | ||||||
|  |             sunsetColor: new THREE.Vector3(0.7, 0.7, 0.8), | ||||||
|  |             atmosphereStrength: 1.8, | ||||||
|  |             sunsetStrength: 0.6 | ||||||
|  |         }, | ||||||
|  |     }), | ||||||
|  |     Callisto: new CelestialBody({ | ||||||
|  |         name: "Callisto", | ||||||
|  |         radius: 4.0, | ||||||
|  |         parent: "Jupiter", | ||||||
|  |         shineColor: 0xff9988, | ||||||
|  |         orbit: { | ||||||
|  |             period: 2.49, | ||||||
|  |             semiMajorAxis: 200., | ||||||
|  |             eccentricity: 0.0045045, | ||||||
|  |             inclination: 0.384285, | ||||||
|  |         }, | ||||||
|  |         rotation: { | ||||||
|  |             period: 100., | ||||||
|  |             inclination: 25.51, | ||||||
|  |             meridianAngle: 0., | ||||||
|  |             offset: 0. | ||||||
|  |         }, | ||||||
|  |         material: { | ||||||
|  |             type: "lambert", | ||||||
|  |             diffuse: {map: "res/callisto/diffuse.jpg"}, | ||||||
|  |         } | ||||||
|  |     }), | ||||||
|  |     Europa: new CelestialBody({ | ||||||
|  |         name: "Europa", | ||||||
|  |         radius: 3.0, | ||||||
|  |         parent: "Jupiter", | ||||||
|  |         shineColor: 0xff9988, | ||||||
|  |         orbit: { | ||||||
|  |             period: 17.76, | ||||||
|  |             semiMajorAxis: 160., | ||||||
|  |             eccentricity: 0.0101, | ||||||
|  |             inclination: 0.470, | ||||||
|  |         }, | ||||||
|  |         rotation: { | ||||||
|  |             period: 150., | ||||||
|  |             inclination: 25.49, | ||||||
|  |             meridianAngle: 0., | ||||||
|  |             offset: 0. | ||||||
|  |         }, | ||||||
|  |         material: { | ||||||
|  |             type: "lambert", | ||||||
|  |             diffuse: {map: "res/europa/diffuse.jpg"}, | ||||||
|  |         } | ||||||
|  |     }), | ||||||
|  |     Io: new CelestialBody({ | ||||||
|  |         name: "Io", | ||||||
|  |         radius: 3.0, | ||||||
|  |         parent: "Jupiter", | ||||||
|  |         shineColor: 0xff9988, | ||||||
|  |         orbit: { | ||||||
|  |             period: 8.85, | ||||||
|  |             semiMajorAxis: 100., | ||||||
|  |             eccentricity: 0.0041, | ||||||
|  |             inclination: 0.040, | ||||||
|  |         }, | ||||||
|  |         rotation: { | ||||||
|  |             period: 100., | ||||||
|  |             inclination: 25.50, | ||||||
|  |             meridianAngle: 0., | ||||||
|  |             offset: 0. | ||||||
|  |         }, | ||||||
|  |         material: { | ||||||
|  |             type: "lambert", | ||||||
|  |             diffuse: {map: "res/io/diffuse.png"}, | ||||||
|  |         } | ||||||
|  |     }), | ||||||
|  |     Saturn: new CelestialBody({ | ||||||
|  |         name: "Saturn", | ||||||
|  |         radius: 94.49, | ||||||
|  |         parent: "Sun", | ||||||
|  |         shineColor: 0x9999ff, | ||||||
|  |         orbit: { | ||||||
|  |             period: 40.0, | ||||||
|  |             semiMajorAxis: 2500., | ||||||
|  |             eccentricity: 0.0542, | ||||||
|  |             inclination: 2.4845 | ||||||
|  |         }, | ||||||
|  |         rotation: { | ||||||
|  |             period: 255.75, | ||||||
|  |             inclination: 28.052, | ||||||
|  |             meridianAngle: 0., | ||||||
|  |             offset: 0. | ||||||
|  |         }, | ||||||
|  |         material: { | ||||||
|  |             type: "lambert", | ||||||
|  |             diffuse: {map: "res/saturn/diffuse.png"}, | ||||||
|  |             bump: {map: "res/saturn/bump.png"}, | ||||||
|  |         }, | ||||||
|  |         atmosphere: { | ||||||
|  |             cloud: { | ||||||
|  |                 map: "res/saturn/clouds.png", | ||||||
|  |                 height: 0.5, | ||||||
|  |                 speed: 0.05 | ||||||
|  |             }, | ||||||
|  |             scattering: true, | ||||||
|  |             atmosphereColor: new THREE.Vector3(0.8, 0.7, 0.5), | ||||||
|  |             sunsetColor: new THREE.Vector3(0.7, 0.7, 0.8), | ||||||
|  |             atmosphereStrength: 1.5, | ||||||
|  |             sunsetStrength: 0.8 | ||||||
|  |         }, | ||||||
|  |         ring: { | ||||||
|  |             map: "res/saturn/ring.png", | ||||||
|  |             lower: 5, | ||||||
|  |             higher: 80, | ||||||
|  |         } | ||||||
|  |     }), | ||||||
|  |     Dione: new CelestialBody({ | ||||||
|  |         name: "Dione", | ||||||
|  |         radius: 5.0, | ||||||
|  |         parent: "Saturn", | ||||||
|  |         shineColor: 0xff9988, | ||||||
|  |         orbit: { | ||||||
|  |             period: 3.0, | ||||||
|  |             semiMajorAxis: 200., | ||||||
|  |             eccentricity: 0.05, | ||||||
|  |             inclination: 0.0049, | ||||||
|  |         }, | ||||||
|  |         rotation: { | ||||||
|  |             period: 130., | ||||||
|  |             inclination: 22.9, | ||||||
|  |             meridianAngle: 0., | ||||||
|  |             offset: 0. | ||||||
|  |         }, | ||||||
|  |         material: { | ||||||
|  |             type: "lambert", | ||||||
|  |             diffuse: {map: "res/dione/diffuse.jpg"}, | ||||||
|  |         } | ||||||
|  |     }), | ||||||
|  |     Titan: new CelestialBody({ | ||||||
|  |         name: "Titan", | ||||||
|  |         radius: 6.0, | ||||||
|  |         parent: "Saturn", | ||||||
|  |         shineColor: 0xff9988, | ||||||
|  |         orbit: { | ||||||
|  |             period: 4.0, | ||||||
|  |             semiMajorAxis: 150., | ||||||
|  |             eccentricity: 0.05, | ||||||
|  |             inclination: 0.0049, | ||||||
|  |         }, | ||||||
|  |         rotation: { | ||||||
|  |             period: 120., | ||||||
|  |             inclination: 1.53, | ||||||
|  |             meridianAngle: 0., | ||||||
|  |             offset: 0. | ||||||
|  |         }, | ||||||
|  |         material: { | ||||||
|  |             type: "lambert", | ||||||
|  |             diffuse: {map: "res/titan/diffuse.jpg"}, | ||||||
|  |         } | ||||||
|  |     }), | ||||||
|  |     Uranus: new CelestialBody({ | ||||||
|  |         name: "Uranus", | ||||||
|  |         radius: 40.07, | ||||||
|  |         parent: "Sun", | ||||||
|  |         shineColor: 0x9999ff, | ||||||
|  |         orbit: { | ||||||
|  |             period: 420.069, | ||||||
|  |             semiMajorAxis: 3000., | ||||||
|  |             eccentricity: 0.0472, | ||||||
|  |             inclination: 0.7699 | ||||||
|  |         }, | ||||||
|  |         rotation: { | ||||||
|  |             period: 413.76, | ||||||
|  |             inclination: 97.722, | ||||||
|  |             meridianAngle: 0., | ||||||
|  |             offset: 0. | ||||||
|  |         }, | ||||||
|  |         material: { | ||||||
|  |             type: "lambert", | ||||||
|  |             diffuse: {map: "res/uranus/diffuse.jpg"}, | ||||||
|  |         }, | ||||||
|  |         ring: { | ||||||
|  |             map: "res/uranus/ring.png", | ||||||
|  |             lower: 10, | ||||||
|  |             higher: 20, | ||||||
|  |         }, | ||||||
|  |         atmosphere: { | ||||||
|  |             scattering: true, | ||||||
|  |             atmosphereColor: new THREE.Vector3(0.5, 0.9, 0.7), | ||||||
|  |             sunsetColor: new THREE.Vector3(0.7, 0.9, 0.8), | ||||||
|  |             atmosphereStrength: 0.2, | ||||||
|  |             sunsetStrength: 0.7 | ||||||
|  |         }, | ||||||
|  |     }), | ||||||
|  |     Neptune: new CelestialBody({ | ||||||
|  |         name: "Neptune", | ||||||
|  |         radius: 38.83, | ||||||
|  |         parent: "Sun", | ||||||
|  |         shineColor: 0x9999ff, | ||||||
|  |         orbit: { | ||||||
|  |             period: 823.965, | ||||||
|  |             semiMajorAxis: 3500., | ||||||
|  |             eccentricity: 0.0097, | ||||||
|  |             inclination: 1.7692 | ||||||
|  |         }, | ||||||
|  |         rotation: { | ||||||
|  |             period: 386.64, | ||||||
|  |             inclination: 28.03, | ||||||
|  |             meridianAngle: 0., | ||||||
|  |             offset: 0. | ||||||
|  |         }, | ||||||
|  |         material: { | ||||||
|  |             type: "lambert", | ||||||
|  |             diffuse: {map: "res/neptune/diffuse.jpg"}, | ||||||
|  |         }, | ||||||
|  |         ring: { | ||||||
|  |             map: "res/neptune/ring.png", | ||||||
|  |             lower: 10, | ||||||
|  |             higher: 20, | ||||||
|  |         } | ||||||
|  |     }), | ||||||
|  |     Pluto: new CelestialBody({ | ||||||
|  |         name: "Pluto", | ||||||
|  |         radius: 15., | ||||||
|  |         parent: "Sun", | ||||||
|  |         shineColor: 0x9999ff, | ||||||
|  |         orbit: { | ||||||
|  |             period: 32.0, | ||||||
|  |             semiMajorAxis: 4000., | ||||||
|  |             eccentricity: 0.2482, | ||||||
|  |             inclination: 17.1449 | ||||||
|  |         }, | ||||||
|  |         rotation: { | ||||||
|  |             period: 153.292944, | ||||||
|  |             inclination: 115.60, | ||||||
|  |             meridianAngle: 0., | ||||||
|  |             offset: 0. | ||||||
|  |         }, | ||||||
|  |         material: { | ||||||
|  |             type: "lambert", | ||||||
|  |             diffuse: {map: "res/pluto/diffuse.jpg"}, | ||||||
|  |         }, | ||||||
|  |     }), | ||||||
|  | } | ||||||
							
								
								
									
										258
									
								
								static/pkg/solar/js/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,258 @@ | |||||||
|  | (function ($) { | ||||||
|  |  | ||||||
|  |     // Creating a number of jQuery plugins that you can use to | ||||||
|  |     // initialize and control the progress meters. | ||||||
|  |  | ||||||
|  |     $.fn.progressInitialize = function () { | ||||||
|  |  | ||||||
|  |         // This function creates the necessary markup for the progress meter | ||||||
|  |         // and sets up a few event listeners. | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         // Loop through all the buttons: | ||||||
|  |  | ||||||
|  |         return this.each(function () { | ||||||
|  |  | ||||||
|  |             var button = $(this), | ||||||
|  |                 progress = 0; | ||||||
|  |  | ||||||
|  |             // Extract the data attributes into the options object. | ||||||
|  |             // If they are missing, they will receive default values. | ||||||
|  |  | ||||||
|  |             var options = $.extend({ | ||||||
|  |                 type: 'background-horizontal', | ||||||
|  |                 loading: 'Loading', | ||||||
|  |                 finished: 'Done' | ||||||
|  |             }, button.data()); | ||||||
|  |  | ||||||
|  |             // Add the data attributes if they are missing from the element. | ||||||
|  |             // They are used by our CSS code to show the messages | ||||||
|  |             button.attr({'data-loading': options.loading, 'data-finished': options.finished}); | ||||||
|  |  | ||||||
|  |             // Add the needed markup for the progress bar to the button | ||||||
|  |             var bar = $('<span class="tz-bar ' + options.type + '">').appendTo(button); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |             // The progress event tells the button to update the progress bar | ||||||
|  |             button.on('progress', function (e, val, absolute, finish) { | ||||||
|  |  | ||||||
|  |                 if (!button.hasClass('in-progress')) { | ||||||
|  |  | ||||||
|  |                     // This is the first progress event for the button (or the | ||||||
|  |                     // first after it has finished in a previous run). Re-initialize | ||||||
|  |                     // the progress and remove some classes that may be left. | ||||||
|  |  | ||||||
|  |                     bar.show(); | ||||||
|  |                     progress = 0; | ||||||
|  |                     button.removeClass('finished').addClass('in-progress') | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 // val, absolute and finish are event data passed by the progressIncrement | ||||||
|  |                 // and progressSet methods that you can see near the end of this file. | ||||||
|  |  | ||||||
|  |                 if (absolute) { | ||||||
|  |                     progress = val; | ||||||
|  |                 } | ||||||
|  |                 else { | ||||||
|  |                     progress += val; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 if (progress >= 100) { | ||||||
|  |                     progress = 100; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 // if(finish){ | ||||||
|  |                 // | ||||||
|  |                 //     button.removeClass('in-progress').addClass('finished'); | ||||||
|  |                 // | ||||||
|  |                 //     bar.delay(500).fadeOut(function(){ | ||||||
|  |                 // | ||||||
|  |                 //         // Trigger the custom progress-finish event | ||||||
|  |                 //         button.trigger('progress-finish'); | ||||||
|  |                 //         setProgress(0); | ||||||
|  |                 //     }); | ||||||
|  |                 // | ||||||
|  |                 // } | ||||||
|  |  | ||||||
|  |                 setProgress(progress); | ||||||
|  |             }); | ||||||
|  |  | ||||||
|  |             function setProgress(percentage) { | ||||||
|  |                 bar.filter('.background-horizontal,.background-bar').width(percentage + '%'); | ||||||
|  |                 bar.filter('.background-vertical').height(percentage + '%'); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     // progressStart simulates activity on the progress meter. Call it first, | ||||||
|  |     // if the progress is going to take a long time to finish. | ||||||
|  |  | ||||||
|  |     $.fn.progressStart = function () { | ||||||
|  |  | ||||||
|  |         var button = this.first(), | ||||||
|  |             last_progress = new Date().getTime(); | ||||||
|  |  | ||||||
|  |         if (button.hasClass('in-progress')) { | ||||||
|  |             // Don't start it a second time! | ||||||
|  |             return this; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         button.on('progress', function () { | ||||||
|  |             last_progress = new Date().getTime(); | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         // Every half a second check whether the progress | ||||||
|  |         // has been incremented in the last two seconds | ||||||
|  |  | ||||||
|  |         var interval = window.setInterval(function () { | ||||||
|  |  | ||||||
|  |             if (new Date().getTime() > 2000 + last_progress) { | ||||||
|  |  | ||||||
|  |                 // There has been no activity for two seconds. Increment the progress | ||||||
|  |                 // bar a little bit to show that something is happening | ||||||
|  |  | ||||||
|  |                 button.progressIncrement(5); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |         }, 500); | ||||||
|  |  | ||||||
|  |         button.on('progress-finish', function () { | ||||||
|  |             window.clearInterval(interval); | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         return button.progressIncrement(10); | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     $.fn.progressFinish = function () { | ||||||
|  |         return this.first().progressSet(100); | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     $.fn.progressIncrement = function (val) { | ||||||
|  |  | ||||||
|  |         val = val || 10; | ||||||
|  |  | ||||||
|  |         var button = this.first(); | ||||||
|  |  | ||||||
|  |         button.trigger('progress', [val]) | ||||||
|  |  | ||||||
|  |         return this; | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     $.fn.progressSet = function (val) { | ||||||
|  |         val = val || 10; | ||||||
|  |  | ||||||
|  |         var finish = false; | ||||||
|  |         if (val >= 100) { | ||||||
|  |             finish = true; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return this.first().trigger('progress', [val, true, finish]); | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     // This function creates a progress meter that | ||||||
|  |     // finishes in a specified amount of time. | ||||||
|  |  | ||||||
|  |     $.fn.progressTimed = function (seconds, cb) { | ||||||
|  |  | ||||||
|  |         var button = this.first(), | ||||||
|  |             bar = button.find('.tz-bar'); | ||||||
|  |  | ||||||
|  |         if (button.is('.in-progress')) { | ||||||
|  |             return this; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // Set a transition declaration for the duration of the meter. | ||||||
|  |         // CSS will do the job of animating the progress bar for us. | ||||||
|  |  | ||||||
|  |         bar.css('transition', seconds + 's linear'); | ||||||
|  |         button.progressSet(99); | ||||||
|  |  | ||||||
|  |         window.setTimeout(function () { | ||||||
|  |             bar.css('transition', ''); | ||||||
|  |             button.progressFinish(); | ||||||
|  |  | ||||||
|  |             if ($.isFunction(cb)) { | ||||||
|  |                 cb(); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |         }, seconds * 1000); | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     function PreLoad(imgs, options) { | ||||||
|  |         this.imgs = (typeof imgs === 'string') ? [imgs] : imgs; | ||||||
|  |         this.opts = $.extend({}, PreLoad.DEFAULTS, options); | ||||||
|  |  | ||||||
|  |         if (this.opts.order === 'ordered') { | ||||||
|  |             this._ordered(); | ||||||
|  |         } else { | ||||||
|  |             this._unordered(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     PreLoad.DEFAULTS = { | ||||||
|  |         order: 'unordered', //无序预加载 | ||||||
|  |         each: null, //每张图片加载完毕后执行 | ||||||
|  |         all: null // 所有图片加载完毕后执行 | ||||||
|  |     }; | ||||||
|  |     PreLoad.prototype._ordered = function () { | ||||||
|  |         var imgs = this.imgs, | ||||||
|  |             opts = this.opts, | ||||||
|  |             count = 0, | ||||||
|  |             len = imgs.length; | ||||||
|  |  | ||||||
|  |         function load() { | ||||||
|  |             var imgObj = new Image(); | ||||||
|  |  | ||||||
|  |             $(imgObj).on('load error', function () { | ||||||
|  |                 opts.each && opts.each(count); | ||||||
|  |                 if (count >= len) { | ||||||
|  |                     //所有图片全部加载完成 | ||||||
|  |                     opts.all && opts.all(); | ||||||
|  |                 } else { | ||||||
|  |                     load(); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 count++; | ||||||
|  |             }); | ||||||
|  |  | ||||||
|  |             imgObj.src = imgs[count]; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         load(); | ||||||
|  |     }; | ||||||
|  |     PreLoad.prototype._unordered = function () {//无序加载 | ||||||
|  |  | ||||||
|  |         var imgs = this.imgs, | ||||||
|  |             opts = this.opts, | ||||||
|  |             count = 0, | ||||||
|  |             len = imgs.length; | ||||||
|  |  | ||||||
|  |         $.each(imgs, function (i, src) { | ||||||
|  |             if (typeof src != 'string') return; | ||||||
|  |  | ||||||
|  |             var imgObj = new Image(); | ||||||
|  |  | ||||||
|  |             $(imgObj).on('load error', function () { | ||||||
|  |  | ||||||
|  |                 opts.each && opts.each(count); | ||||||
|  |  | ||||||
|  |                 if (count >= len - 1) { | ||||||
|  |                     opts.all && opts.all(); | ||||||
|  |                 } | ||||||
|  |                 count++; | ||||||
|  |             }); | ||||||
|  |  | ||||||
|  |             imgObj.src = src; | ||||||
|  |         }); | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     $.extend({ | ||||||
|  |         preLoad: function (imgs, opts) { | ||||||
|  |             new PreLoad(imgs, opts); | ||||||
|  |         } | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  | })(jQuery); | ||||||
							
								
								
									
										300
									
								
								static/pkg/solar/js/libs/FirstPersonControls.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,300 @@ | |||||||
|  | /** | ||||||
|  |  * @author mrdoob / http://mrdoob.com/ | ||||||
|  |  * @author alteredq / http://alteredqualia.com/ | ||||||
|  |  * @author paulirish / http://paulirish.com/ | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | THREE.FirstPersonControls = function ( object, domElement ) { | ||||||
|  |  | ||||||
|  | 	this.object = object; | ||||||
|  | 	this.target = new THREE.Vector3( 0, 0, 0 ); | ||||||
|  |  | ||||||
|  | 	this.domElement = ( domElement !== undefined ) ? domElement : document; | ||||||
|  |  | ||||||
|  | 	this.enabled = true; | ||||||
|  |  | ||||||
|  | 	this.movementSpeed = 1.0; | ||||||
|  | 	this.lookSpeed = 0.005; | ||||||
|  |  | ||||||
|  | 	this.lookVertical = true; | ||||||
|  | 	this.autoForward = false; | ||||||
|  |  | ||||||
|  | 	this.activeLook = true; | ||||||
|  |  | ||||||
|  | 	this.heightSpeed = false; | ||||||
|  | 	this.heightCoef = 1.0; | ||||||
|  | 	this.heightMin = 0.0; | ||||||
|  | 	this.heightMax = 1.0; | ||||||
|  |  | ||||||
|  | 	this.constrainVertical = false; | ||||||
|  | 	this.verticalMin = 0; | ||||||
|  | 	this.verticalMax = Math.PI; | ||||||
|  |  | ||||||
|  | 	this.autoSpeedFactor = 0.0; | ||||||
|  |  | ||||||
|  | 	this.mouseX = 0; | ||||||
|  | 	this.mouseY = 0; | ||||||
|  |  | ||||||
|  | 	this.lat = 0; | ||||||
|  | 	this.lon = 0; | ||||||
|  | 	this.phi = 0; | ||||||
|  | 	this.theta = 0; | ||||||
|  |  | ||||||
|  | 	this.moveForward = false; | ||||||
|  | 	this.moveBackward = false; | ||||||
|  | 	this.moveLeft = false; | ||||||
|  | 	this.moveRight = false; | ||||||
|  |  | ||||||
|  | 	this.mouseDragOn = false; | ||||||
|  |  | ||||||
|  | 	this.viewHalfX = 0; | ||||||
|  | 	this.viewHalfY = 0; | ||||||
|  |  | ||||||
|  | 	if ( this.domElement !== document ) { | ||||||
|  |  | ||||||
|  | 		this.domElement.setAttribute( 'tabindex', - 1 ); | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// | ||||||
|  |  | ||||||
|  | 	this.handleResize = function () { | ||||||
|  |  | ||||||
|  | 		if ( this.domElement === document ) { | ||||||
|  |  | ||||||
|  | 			this.viewHalfX = window.innerWidth / 2; | ||||||
|  | 			this.viewHalfY = window.innerHeight / 2; | ||||||
|  |  | ||||||
|  | 		} else { | ||||||
|  |  | ||||||
|  | 			this.viewHalfX = this.domElement.offsetWidth / 2; | ||||||
|  | 			this.viewHalfY = this.domElement.offsetHeight / 2; | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	this.onMouseDown = function ( event ) { | ||||||
|  |  | ||||||
|  | 		if ( this.domElement !== document ) { | ||||||
|  |  | ||||||
|  | 			this.domElement.focus(); | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		event.preventDefault(); | ||||||
|  | 		event.stopPropagation(); | ||||||
|  |  | ||||||
|  | 		if ( this.activeLook ) { | ||||||
|  |  | ||||||
|  | 			switch ( event.button ) { | ||||||
|  |  | ||||||
|  | 				case 0: this.moveForward = true; break; | ||||||
|  | 				case 2: this.moveBackward = true; break; | ||||||
|  |  | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		this.mouseDragOn = true; | ||||||
|  |  | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	this.onMouseUp = function ( event ) { | ||||||
|  |  | ||||||
|  | 		event.preventDefault(); | ||||||
|  | 		event.stopPropagation(); | ||||||
|  |  | ||||||
|  | 		if ( this.activeLook ) { | ||||||
|  |  | ||||||
|  | 			switch ( event.button ) { | ||||||
|  |  | ||||||
|  | 				case 0: this.moveForward = false; break; | ||||||
|  | 				case 2: this.moveBackward = false; break; | ||||||
|  |  | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		this.mouseDragOn = false; | ||||||
|  |  | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	this.onMouseMove = function ( event ) { | ||||||
|  |  | ||||||
|  | 		if ( this.domElement === document ) { | ||||||
|  |  | ||||||
|  | 			this.mouseX = event.pageX - this.viewHalfX; | ||||||
|  | 			this.mouseY = event.pageY - this.viewHalfY; | ||||||
|  |  | ||||||
|  | 		} else { | ||||||
|  |  | ||||||
|  | 			this.mouseX = event.pageX - this.domElement.offsetLeft - this.viewHalfX; | ||||||
|  | 			this.mouseY = event.pageY - this.domElement.offsetTop - this.viewHalfY; | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	this.onKeyDown = function ( event ) { | ||||||
|  |  | ||||||
|  | 		//event.preventDefault(); | ||||||
|  |  | ||||||
|  | 		switch ( event.keyCode ) { | ||||||
|  |  | ||||||
|  | 			case 38: /*up*/ | ||||||
|  | 			case 87: /*W*/ this.moveForward = true; break; | ||||||
|  |  | ||||||
|  | 			case 37: /*left*/ | ||||||
|  | 			case 65: /*A*/ this.moveLeft = true; break; | ||||||
|  |  | ||||||
|  | 			case 40: /*down*/ | ||||||
|  | 			case 83: /*S*/ this.moveBackward = true; break; | ||||||
|  |  | ||||||
|  | 			case 39: /*right*/ | ||||||
|  | 			case 68: /*D*/ this.moveRight = true; break; | ||||||
|  |  | ||||||
|  | 			case 82: /*R*/ this.moveUp = true; break; | ||||||
|  | 			case 70: /*F*/ this.moveDown = true; break; | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	this.onKeyUp = function ( event ) { | ||||||
|  |  | ||||||
|  | 		switch ( event.keyCode ) { | ||||||
|  |  | ||||||
|  | 			case 38: /*up*/ | ||||||
|  | 			case 87: /*W*/ this.moveForward = false; break; | ||||||
|  |  | ||||||
|  | 			case 37: /*left*/ | ||||||
|  | 			case 65: /*A*/ this.moveLeft = false; break; | ||||||
|  |  | ||||||
|  | 			case 40: /*down*/ | ||||||
|  | 			case 83: /*S*/ this.moveBackward = false; break; | ||||||
|  |  | ||||||
|  | 			case 39: /*right*/ | ||||||
|  | 			case 68: /*D*/ this.moveRight = false; break; | ||||||
|  |  | ||||||
|  | 			case 82: /*R*/ this.moveUp = false; break; | ||||||
|  | 			case 70: /*F*/ this.moveDown = false; break; | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	this.update = function( delta ) { | ||||||
|  |  | ||||||
|  | 		if ( this.enabled === false ) return; | ||||||
|  |  | ||||||
|  | 		if ( this.heightSpeed ) { | ||||||
|  |  | ||||||
|  | 			var y = THREE.Math.clamp( this.object.position.y, this.heightMin, this.heightMax ); | ||||||
|  | 			var heightDelta = y - this.heightMin; | ||||||
|  |  | ||||||
|  | 			this.autoSpeedFactor = delta * ( heightDelta * this.heightCoef ); | ||||||
|  |  | ||||||
|  | 		} else { | ||||||
|  |  | ||||||
|  | 			this.autoSpeedFactor = 0.0; | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		var actualMoveSpeed = delta * this.movementSpeed; | ||||||
|  |  | ||||||
|  | 		if ( this.moveForward || ( this.autoForward && ! this.moveBackward ) ) this.object.translateZ( - ( actualMoveSpeed + this.autoSpeedFactor ) ); | ||||||
|  | 		if ( this.moveBackward ) this.object.translateZ( actualMoveSpeed ); | ||||||
|  |  | ||||||
|  | 		if ( this.moveLeft ) this.object.translateX( - actualMoveSpeed ); | ||||||
|  | 		if ( this.moveRight ) this.object.translateX( actualMoveSpeed ); | ||||||
|  |  | ||||||
|  | 		if ( this.moveUp ) this.object.translateY( actualMoveSpeed ); | ||||||
|  | 		if ( this.moveDown ) this.object.translateY( - actualMoveSpeed ); | ||||||
|  |  | ||||||
|  | 		var actualLookSpeed = delta * this.lookSpeed; | ||||||
|  |  | ||||||
|  | 		if ( ! this.activeLook ) { | ||||||
|  |  | ||||||
|  | 			actualLookSpeed = 0; | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		var verticalLookRatio = 1; | ||||||
|  |  | ||||||
|  | 		if ( this.constrainVertical ) { | ||||||
|  |  | ||||||
|  | 			verticalLookRatio = Math.PI / ( this.verticalMax - this.verticalMin ); | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		this.lon += this.mouseX * actualLookSpeed; | ||||||
|  | 		if ( this.lookVertical ) this.lat -= this.mouseY * actualLookSpeed * verticalLookRatio; | ||||||
|  |  | ||||||
|  | 		this.lat = Math.max( - 85, Math.min( 85, this.lat ) ); | ||||||
|  | 		this.phi = THREE.Math.degToRad( 90 - this.lat ); | ||||||
|  |  | ||||||
|  | 		this.theta = THREE.Math.degToRad( this.lon ); | ||||||
|  |  | ||||||
|  | 		if ( this.constrainVertical ) { | ||||||
|  |  | ||||||
|  | 			this.phi = THREE.Math.mapLinear( this.phi, 0, Math.PI, this.verticalMin, this.verticalMax ); | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		var targetPosition = this.target, | ||||||
|  | 			position = this.object.position; | ||||||
|  |  | ||||||
|  | 		targetPosition.x = position.x + 100 * Math.sin( this.phi ) * Math.cos( this.theta ); | ||||||
|  | 		targetPosition.y = position.y + 100 * Math.cos( this.phi ); | ||||||
|  | 		targetPosition.z = position.z + 100 * Math.sin( this.phi ) * Math.sin( this.theta ); | ||||||
|  |  | ||||||
|  | 		this.object.lookAt( targetPosition ); | ||||||
|  |  | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	function contextmenu( event ) { | ||||||
|  |  | ||||||
|  | 		event.preventDefault(); | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	this.dispose = function() { | ||||||
|  |  | ||||||
|  | 		this.domElement.removeEventListener( 'contextmenu', contextmenu, false ); | ||||||
|  | 		this.domElement.removeEventListener( 'mousedown', _onMouseDown, false ); | ||||||
|  | 		this.domElement.removeEventListener( 'mousemove', _onMouseMove, false ); | ||||||
|  | 		this.domElement.removeEventListener( 'mouseup', _onMouseUp, false ); | ||||||
|  |  | ||||||
|  | 		window.removeEventListener( 'keydown', _onKeyDown, false ); | ||||||
|  | 		window.removeEventListener( 'keyup', _onKeyUp, false ); | ||||||
|  |  | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	var _onMouseMove = bind( this, this.onMouseMove ); | ||||||
|  | 	var _onMouseDown = bind( this, this.onMouseDown ); | ||||||
|  | 	var _onMouseUp = bind( this, this.onMouseUp ); | ||||||
|  | 	var _onKeyDown = bind( this, this.onKeyDown ); | ||||||
|  | 	var _onKeyUp = bind( this, this.onKeyUp ); | ||||||
|  |  | ||||||
|  | 	this.domElement.addEventListener( 'contextmenu', contextmenu, false ); | ||||||
|  | 	this.domElement.addEventListener( 'mousemove', _onMouseMove, false ); | ||||||
|  | 	this.domElement.addEventListener( 'mousedown', _onMouseDown, false ); | ||||||
|  | 	this.domElement.addEventListener( 'mouseup', _onMouseUp, false ); | ||||||
|  |  | ||||||
|  | 	window.addEventListener( 'keydown', _onKeyDown, false ); | ||||||
|  | 	window.addEventListener( 'keyup', _onKeyUp, false ); | ||||||
|  |  | ||||||
|  | 	function bind( scope, fn ) { | ||||||
|  |  | ||||||
|  | 		return function () { | ||||||
|  |  | ||||||
|  | 			fn.apply( scope, arguments ); | ||||||
|  |  | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	this.handleResize(); | ||||||
|  |  | ||||||
|  | }; | ||||||
							
								
								
									
										501
									
								
								static/pkg/solar/js/libs/GPUParticleSystem.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,501 @@ | |||||||
|  | /* | ||||||
|  |  * GPU Particle System | ||||||
|  |  * @author flimshaw - Charlie Hoey - http://charliehoey.com | ||||||
|  |  * | ||||||
|  |  * A simple to use, general purpose GPU system. Particles are spawn-and-forget with | ||||||
|  |  * several options available, and do not require monitoring or cleanup after spawning. | ||||||
|  |  * Because the paths of all particles are completely deterministic once spawned, the scale | ||||||
|  |  * and direction of time is also variable. | ||||||
|  |  * | ||||||
|  |  * Currently uses a static wrapping perlin noise texture for turbulence, and a small png texture for | ||||||
|  |  * particles, but adding support for a particle texture atlas or changing to a different type of turbulence | ||||||
|  |  * would be a fairly light day's work. | ||||||
|  |  * | ||||||
|  |  * Shader and javascript packing code derrived from several Stack Overflow examples. | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | THREE.GPUParticleSystem = function( options ) { | ||||||
|  |  | ||||||
|  | 	THREE.Object3D.apply( this, arguments ); | ||||||
|  |  | ||||||
|  | 	options = options || {}; | ||||||
|  |  | ||||||
|  | 	// parse options and use defaults | ||||||
|  |  | ||||||
|  | 	this.PARTICLE_COUNT = options.maxParticles || 1000000; | ||||||
|  | 	this.PARTICLE_CONTAINERS = options.containerCount || 1; | ||||||
|  |  | ||||||
|  | 	this.PARTICLE_NOISE_TEXTURE = options.particleNoiseTex || null; | ||||||
|  | 	this.PARTICLE_SPRITE_TEXTURE = options.particleSpriteTex || null; | ||||||
|  |  | ||||||
|  | 	this.PARTICLES_PER_CONTAINER = Math.ceil( this.PARTICLE_COUNT / this.PARTICLE_CONTAINERS ); | ||||||
|  | 	this.PARTICLE_CURSOR = 0; | ||||||
|  | 	this.time = 0; | ||||||
|  | 	this.particleContainers = []; | ||||||
|  | 	this.rand = []; | ||||||
|  |  | ||||||
|  | 	// custom vertex and fragement shader | ||||||
|  |  | ||||||
|  | 	var GPUParticleShader = { | ||||||
|  |  | ||||||
|  | 		vertexShader: [ | ||||||
|  |  | ||||||
|  | 			'uniform float uTime;', | ||||||
|  | 			'uniform float uScale;', | ||||||
|  | 			'uniform sampler2D tNoise;', | ||||||
|  |  | ||||||
|  | 			'attribute vec3 positionStart;', | ||||||
|  | 			'attribute float startTime;', | ||||||
|  | 			'attribute vec3 velocity;', | ||||||
|  | 			'attribute float turbulence;', | ||||||
|  | 			'attribute vec3 color;', | ||||||
|  | 			'attribute float size;', | ||||||
|  | 			'attribute float lifeTime;', | ||||||
|  |  | ||||||
|  | 			'varying vec4 vColor;', | ||||||
|  | 			'varying float lifeLeft;', | ||||||
|  |  | ||||||
|  | 			'void main() {', | ||||||
|  |  | ||||||
|  | 			// unpack things from our attributes' | ||||||
|  |  | ||||||
|  | 			'	vColor = vec4( color, 1.0 );', | ||||||
|  |  | ||||||
|  | 			// convert our velocity back into a value we can use' | ||||||
|  |  | ||||||
|  | 			'	vec3 newPosition;', | ||||||
|  | 			'	vec3 v;', | ||||||
|  |  | ||||||
|  | 			'	float timeElapsed = uTime - startTime;', | ||||||
|  |  | ||||||
|  | 			'	lifeLeft = 1.0 - ( timeElapsed / lifeTime );', | ||||||
|  |  | ||||||
|  | 			'	gl_PointSize = ( uScale * size ) * lifeLeft;', | ||||||
|  |  | ||||||
|  | 			'	v.x = ( velocity.x - 0.5 ) * 3.0;', | ||||||
|  | 			'	v.y = ( velocity.y - 0.5 ) * 3.0;', | ||||||
|  | 			'	v.z = ( velocity.z - 0.5 ) * 3.0;', | ||||||
|  |  | ||||||
|  | 			'	newPosition = positionStart + ( v * 10.0 ) * timeElapsed;', | ||||||
|  |  | ||||||
|  | 			'	vec3 noise = texture2D( tNoise, vec2( newPosition.x * 0.015 + ( uTime * 0.05 ), newPosition.y * 0.02 + ( uTime * 0.015 ) ) ).rgb;', | ||||||
|  | 			'	vec3 noiseVel = ( noise.rgb - 0.5 ) * 30.0;', | ||||||
|  |  | ||||||
|  | 			'	newPosition = mix( newPosition, newPosition + vec3( noiseVel * ( turbulence * 5.0 ) ), ( timeElapsed / lifeTime ) );', | ||||||
|  |  | ||||||
|  | 			'	if( v.y > 0. && v.y < .05 ) {', | ||||||
|  |  | ||||||
|  | 			'		lifeLeft = 0.0;', | ||||||
|  |  | ||||||
|  | 			'	}', | ||||||
|  |  | ||||||
|  | 			'	if( v.x < - 1.45 ) {', | ||||||
|  |  | ||||||
|  | 			'		lifeLeft = 0.0;', | ||||||
|  |  | ||||||
|  | 			'	}', | ||||||
|  |  | ||||||
|  | 			'	if( timeElapsed > 0.0 ) {', | ||||||
|  |  | ||||||
|  | 			'		gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );', | ||||||
|  |  | ||||||
|  | 			'	} else {', | ||||||
|  |  | ||||||
|  | 			'		gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', | ||||||
|  | 			'		lifeLeft = 0.0;', | ||||||
|  | 			'		gl_PointSize = 0.;', | ||||||
|  |  | ||||||
|  | 			'	}', | ||||||
|  |  | ||||||
|  | 			'}' | ||||||
|  |  | ||||||
|  | 		].join( '\n' ), | ||||||
|  |  | ||||||
|  | 		fragmentShader: [ | ||||||
|  |  | ||||||
|  | 			'float scaleLinear( float value, vec2 valueDomain ) {', | ||||||
|  |  | ||||||
|  | 			'	return ( value - valueDomain.x ) / ( valueDomain.y - valueDomain.x );', | ||||||
|  |  | ||||||
|  | 			'}', | ||||||
|  |  | ||||||
|  | 			'float scaleLinear( float value, vec2 valueDomain, vec2 valueRange ) {', | ||||||
|  |  | ||||||
|  | 			'	return mix( valueRange.x, valueRange.y, scaleLinear( value, valueDomain ) );', | ||||||
|  |  | ||||||
|  | 			'}', | ||||||
|  |  | ||||||
|  | 			'varying vec4 vColor;', | ||||||
|  | 			'varying float lifeLeft;', | ||||||
|  |  | ||||||
|  | 			'uniform sampler2D tSprite;', | ||||||
|  |  | ||||||
|  | 			'void main() {', | ||||||
|  |  | ||||||
|  | 			'	float alpha = 0.;', | ||||||
|  |  | ||||||
|  | 			'	if( lifeLeft > 0.995 ) {', | ||||||
|  |  | ||||||
|  | 			'		alpha = scaleLinear( lifeLeft, vec2( 1.0, 0.995 ), vec2( 0.0, 1.0 ) );', | ||||||
|  |  | ||||||
|  | 			'	} else {', | ||||||
|  |  | ||||||
|  | 			'		alpha = lifeLeft * 0.75;', | ||||||
|  |  | ||||||
|  | 			'	}', | ||||||
|  |  | ||||||
|  | 			'	vec4 tex = texture2D( tSprite, gl_PointCoord );', | ||||||
|  | 			'	gl_FragColor = vec4( vColor.rgb * tex.a, alpha * tex.a );', | ||||||
|  |  | ||||||
|  | 			'}' | ||||||
|  |  | ||||||
|  | 		].join( '\n' ) | ||||||
|  |  | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	// preload a million random numbers | ||||||
|  |  | ||||||
|  | 	var i; | ||||||
|  |  | ||||||
|  | 	for ( i = 1e5; i > 0; i-- ) { | ||||||
|  |  | ||||||
|  | 		this.rand.push( Math.random() - 0.5 ); | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	this.random = function() { | ||||||
|  |  | ||||||
|  | 		return ++ i >= this.rand.length ? this.rand[ i = 1 ] : this.rand[ i ]; | ||||||
|  |  | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	var textureLoader = new THREE.TextureLoader(); | ||||||
|  |  | ||||||
|  | 	this.particleNoiseTex = this.PARTICLE_NOISE_TEXTURE || textureLoader.load( 'res/comet/perlin-512.png' ); | ||||||
|  | 	this.particleNoiseTex.wrapS = this.particleNoiseTex.wrapT = THREE.RepeatWrapping; | ||||||
|  |  | ||||||
|  | 	this.particleSpriteTex = this.PARTICLE_SPRITE_TEXTURE || textureLoader.load( 'res/comet/particle2.png' ); | ||||||
|  | 	this.particleSpriteTex.wrapS = this.particleSpriteTex.wrapT = THREE.RepeatWrapping; | ||||||
|  |  | ||||||
|  | 	this.particleShaderMat = new THREE.ShaderMaterial( { | ||||||
|  | 		transparent: true, | ||||||
|  | 		depthWrite: false, | ||||||
|  | 		uniforms: { | ||||||
|  | 			'uTime': { | ||||||
|  | 				value: 0.0 | ||||||
|  | 			}, | ||||||
|  | 			'uScale': { | ||||||
|  | 				value: 1.0 | ||||||
|  | 			}, | ||||||
|  | 			'tNoise': { | ||||||
|  | 				value: this.particleNoiseTex | ||||||
|  | 			}, | ||||||
|  | 			'tSprite': { | ||||||
|  | 				value: this.particleSpriteTex | ||||||
|  | 			} | ||||||
|  | 		}, | ||||||
|  | 		blending: THREE.AdditiveBlending, | ||||||
|  | 		vertexShader: GPUParticleShader.vertexShader, | ||||||
|  | 		fragmentShader: GPUParticleShader.fragmentShader | ||||||
|  | 	} ); | ||||||
|  |  | ||||||
|  | 	// define defaults for all values | ||||||
|  |  | ||||||
|  | 	this.particleShaderMat.defaultAttributeValues.particlePositionsStartTime = [ 0, 0, 0, 0 ]; | ||||||
|  | 	this.particleShaderMat.defaultAttributeValues.particleVelColSizeLife = [ 0, 0, 0, 0 ]; | ||||||
|  |  | ||||||
|  | 	this.init = function() { | ||||||
|  |  | ||||||
|  | 		for ( var i = 0; i < this.PARTICLE_CONTAINERS; i ++ ) { | ||||||
|  |  | ||||||
|  | 			var c = new THREE.GPUParticleContainer( this.PARTICLES_PER_CONTAINER, this ); | ||||||
|  | 			this.particleContainers.push( c ); | ||||||
|  | 			this.add( c ); | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	this.spawnParticle = function( options ) { | ||||||
|  |  | ||||||
|  | 		this.PARTICLE_CURSOR ++; | ||||||
|  |  | ||||||
|  | 		if ( this.PARTICLE_CURSOR >= this.PARTICLE_COUNT ) { | ||||||
|  |  | ||||||
|  | 			this.PARTICLE_CURSOR = 1; | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		var currentContainer = this.particleContainers[ Math.floor( this.PARTICLE_CURSOR / this.PARTICLES_PER_CONTAINER ) ]; | ||||||
|  |  | ||||||
|  | 		currentContainer.spawnParticle( options ); | ||||||
|  |  | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	this.update = function( time ) { | ||||||
|  |  | ||||||
|  | 		for ( var i = 0; i < this.PARTICLE_CONTAINERS; i ++ ) { | ||||||
|  |  | ||||||
|  | 			this.particleContainers[ i ].update( time ); | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	this.dispose = function() { | ||||||
|  |  | ||||||
|  | 		this.particleShaderMat.dispose(); | ||||||
|  | 		this.particleNoiseTex.dispose(); | ||||||
|  | 		this.particleSpriteTex.dispose(); | ||||||
|  |  | ||||||
|  | 		for ( var i = 0; i < this.PARTICLE_CONTAINERS; i ++ ) { | ||||||
|  |  | ||||||
|  | 			this.particleContainers[ i ].dispose(); | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	this.init(); | ||||||
|  |  | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | THREE.GPUParticleSystem.prototype = Object.create( THREE.Object3D.prototype ); | ||||||
|  | THREE.GPUParticleSystem.prototype.constructor = THREE.GPUParticleSystem; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | // Subclass for particle containers, allows for very large arrays to be spread out | ||||||
|  |  | ||||||
|  | THREE.GPUParticleContainer = function( maxParticles, particleSystem ) { | ||||||
|  |  | ||||||
|  | 	THREE.Object3D.apply( this, arguments ); | ||||||
|  |  | ||||||
|  | 	this.PARTICLE_COUNT = maxParticles || 100000; | ||||||
|  | 	this.PARTICLE_CURSOR = 0; | ||||||
|  | 	this.time = 0; | ||||||
|  | 	this.offset = 0; | ||||||
|  | 	this.count = 0; | ||||||
|  | 	this.DPR = window.devicePixelRatio; | ||||||
|  | 	this.GPUParticleSystem = particleSystem; | ||||||
|  | 	this.particleUpdate = false; | ||||||
|  |  | ||||||
|  | 	// geometry | ||||||
|  |  | ||||||
|  | 	this.particleShaderGeo = new THREE.BufferGeometry(); | ||||||
|  |  | ||||||
|  | 	this.particleShaderGeo.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( this.PARTICLE_COUNT * 3 ), 3 ).setDynamic( true ) ); | ||||||
|  | 	this.particleShaderGeo.addAttribute( 'positionStart', new THREE.BufferAttribute( new Float32Array( this.PARTICLE_COUNT * 3 ), 3 ).setDynamic( true ) ); | ||||||
|  | 	this.particleShaderGeo.addAttribute( 'startTime', new THREE.BufferAttribute( new Float32Array( this.PARTICLE_COUNT ), 1 ).setDynamic( true ) ); | ||||||
|  | 	this.particleShaderGeo.addAttribute( 'velocity', new THREE.BufferAttribute( new Float32Array( this.PARTICLE_COUNT * 3 ), 3 ).setDynamic( true ) ); | ||||||
|  | 	this.particleShaderGeo.addAttribute( 'turbulence', new THREE.BufferAttribute( new Float32Array( this.PARTICLE_COUNT ), 1 ).setDynamic( true ) ); | ||||||
|  | 	this.particleShaderGeo.addAttribute( 'color', new THREE.BufferAttribute( new Float32Array( this.PARTICLE_COUNT * 3 ), 3 ).setDynamic( true ) ); | ||||||
|  | 	this.particleShaderGeo.addAttribute( 'size', new THREE.BufferAttribute( new Float32Array( this.PARTICLE_COUNT ), 1 ).setDynamic( true ) ); | ||||||
|  | 	this.particleShaderGeo.addAttribute( 'lifeTime', new THREE.BufferAttribute( new Float32Array( this.PARTICLE_COUNT ), 1 ).setDynamic( true ) ); | ||||||
|  |  | ||||||
|  | 	// material | ||||||
|  |  | ||||||
|  | 	this.particleShaderMat = this.GPUParticleSystem.particleShaderMat; | ||||||
|  |  | ||||||
|  | 	var position = new THREE.Vector3(); | ||||||
|  | 	var velocity = new THREE.Vector3(); | ||||||
|  | 	var color = new THREE.Color(); | ||||||
|  |  | ||||||
|  | 	this.spawnParticle = function( options ) { | ||||||
|  |  | ||||||
|  | 		var positionStartAttribute = this.particleShaderGeo.getAttribute( 'positionStart' ); | ||||||
|  | 		var startTimeAttribute = this.particleShaderGeo.getAttribute( 'startTime' ); | ||||||
|  | 		var velocityAttribute = this.particleShaderGeo.getAttribute( 'velocity' ); | ||||||
|  | 		var turbulenceAttribute = this.particleShaderGeo.getAttribute( 'turbulence' ); | ||||||
|  | 		var colorAttribute = this.particleShaderGeo.getAttribute( 'color' ); | ||||||
|  | 		var sizeAttribute = this.particleShaderGeo.getAttribute( 'size' ); | ||||||
|  | 		var lifeTimeAttribute = this.particleShaderGeo.getAttribute( 'lifeTime' ); | ||||||
|  |  | ||||||
|  | 		options = options || {}; | ||||||
|  |  | ||||||
|  | 		// setup reasonable default values for all arguments | ||||||
|  |  | ||||||
|  | 		position = options.position !== undefined ? position.copy( options.position ) : position.set( 0, 0, 0 ); | ||||||
|  | 		velocity = options.velocity !== undefined ? velocity.copy( options.velocity ) : velocity.set( 0, 0, 0 ); | ||||||
|  | 		color = options.color !== undefined ? color.set( options.color ) : color.set( 0xffffff ); | ||||||
|  |  | ||||||
|  | 		var positionRandomness = options.positionRandomness !== undefined ? options.positionRandomness : 0; | ||||||
|  | 		var velocityRandomness = options.velocityRandomness !== undefined ? options.velocityRandomness : 0; | ||||||
|  | 		var colorRandomness = options.colorRandomness !== undefined ? options.colorRandomness : 1; | ||||||
|  | 		var turbulence = options.turbulence !== undefined ? options.turbulence : 1; | ||||||
|  | 		var lifetime = options.lifetime !== undefined ? options.lifetime : 5; | ||||||
|  | 		var size = options.size !== undefined ? options.size : 10; | ||||||
|  | 		var sizeRandomness = options.sizeRandomness !== undefined ? options.sizeRandomness : 0; | ||||||
|  | 		var smoothPosition = options.smoothPosition !== undefined ? options.smoothPosition : false; | ||||||
|  |  | ||||||
|  | 		if ( this.DPR !== undefined ) size *= this.DPR; | ||||||
|  |  | ||||||
|  | 		var i = this.PARTICLE_CURSOR; | ||||||
|  |  | ||||||
|  | 		// position | ||||||
|  |  | ||||||
|  | 		positionStartAttribute.array[ i * 3 + 0 ] = position.x + ( particleSystem.random() * positionRandomness ); | ||||||
|  | 		positionStartAttribute.array[ i * 3 + 1 ] = position.y + ( particleSystem.random() * positionRandomness ); | ||||||
|  | 		positionStartAttribute.array[ i * 3 + 2 ] = position.z + ( particleSystem.random() * positionRandomness ); | ||||||
|  |  | ||||||
|  | 		if ( smoothPosition === true ) { | ||||||
|  |  | ||||||
|  | 			positionStartAttribute.array[ i * 3 + 0 ] += - ( velocity.x * particleSystem.random() ); | ||||||
|  | 			positionStartAttribute.array[ i * 3 + 1 ] += - ( velocity.y * particleSystem.random() ); | ||||||
|  | 			positionStartAttribute.array[ i * 3 + 2 ] += - ( velocity.z * particleSystem.random() ); | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// velocity | ||||||
|  |  | ||||||
|  | 		var maxVel = 2; | ||||||
|  |  | ||||||
|  | 		var velX = velocity.x + particleSystem.random() * velocityRandomness; | ||||||
|  | 		var velY = velocity.y + particleSystem.random() * velocityRandomness; | ||||||
|  | 		var velZ = velocity.z + particleSystem.random() * velocityRandomness; | ||||||
|  |  | ||||||
|  | 		velX = THREE.Math.clamp( ( velX - ( - maxVel ) ) / ( maxVel - ( - maxVel ) ), 0, 1 ); | ||||||
|  | 		velY = THREE.Math.clamp( ( velY - ( - maxVel ) ) / ( maxVel - ( - maxVel ) ), 0, 1 ); | ||||||
|  | 		velZ = THREE.Math.clamp( ( velZ - ( - maxVel ) ) / ( maxVel - ( - maxVel ) ), 0, 1 ); | ||||||
|  |  | ||||||
|  | 		velocityAttribute.array[ i * 3 + 0 ] = velX; | ||||||
|  | 		velocityAttribute.array[ i * 3 + 1 ] = velY; | ||||||
|  | 		velocityAttribute.array[ i * 3 + 2 ] = velZ; | ||||||
|  |  | ||||||
|  | 		// color | ||||||
|  |  | ||||||
|  | 		color.r = THREE.Math.clamp( color.r + particleSystem.random() * colorRandomness, 0, 1 ); | ||||||
|  | 		color.g = THREE.Math.clamp( color.g + particleSystem.random() * colorRandomness, 0, 1 ); | ||||||
|  | 		color.b = THREE.Math.clamp( color.b + particleSystem.random() * colorRandomness, 0, 1 ); | ||||||
|  |  | ||||||
|  | 		colorAttribute.array[ i * 3 + 0 ] = color.r; | ||||||
|  | 		colorAttribute.array[ i * 3 + 1 ] = color.g; | ||||||
|  | 		colorAttribute.array[ i * 3 + 2 ] = color.b; | ||||||
|  |  | ||||||
|  | 		// turbulence, size, lifetime and starttime | ||||||
|  |  | ||||||
|  | 		turbulenceAttribute.array[ i ] = turbulence; | ||||||
|  | 		sizeAttribute.array[ i ] = size + particleSystem.random() * sizeRandomness; | ||||||
|  | 		lifeTimeAttribute.array[ i ] = lifetime; | ||||||
|  | 		startTimeAttribute.array[ i ] = this.time + particleSystem.random() * 2e-2; | ||||||
|  |  | ||||||
|  | 		// offset | ||||||
|  |  | ||||||
|  | 		if ( this.offset === 0 ) { | ||||||
|  |  | ||||||
|  | 			this.offset = this.PARTICLE_CURSOR; | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// counter and cursor | ||||||
|  |  | ||||||
|  | 		this.count ++; | ||||||
|  | 		this.PARTICLE_CURSOR ++; | ||||||
|  |  | ||||||
|  | 		if ( this.PARTICLE_CURSOR >= this.PARTICLE_COUNT ) { | ||||||
|  |  | ||||||
|  | 			this.PARTICLE_CURSOR = 0; | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		this.particleUpdate = true; | ||||||
|  |  | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	this.init = function() { | ||||||
|  |  | ||||||
|  | 		this.particleSystem = new THREE.Points( this.particleShaderGeo, this.particleShaderMat ); | ||||||
|  | 		this.particleSystem.frustumCulled = false; | ||||||
|  | 		this.add( this.particleSystem ); | ||||||
|  |  | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	this.update = function( time ) { | ||||||
|  |  | ||||||
|  | 		this.time = time; | ||||||
|  | 		this.particleShaderMat.uniforms.uTime.value = time; | ||||||
|  |  | ||||||
|  | 		this.geometryUpdate(); | ||||||
|  |  | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	this.geometryUpdate = function() { | ||||||
|  |  | ||||||
|  | 		if ( this.particleUpdate === true ) { | ||||||
|  |  | ||||||
|  | 			this.particleUpdate = false; | ||||||
|  |  | ||||||
|  | 			var positionStartAttribute = this.particleShaderGeo.getAttribute( 'positionStart' ); | ||||||
|  | 			var startTimeAttribute = this.particleShaderGeo.getAttribute( 'startTime' ); | ||||||
|  | 			var velocityAttribute = this.particleShaderGeo.getAttribute( 'velocity' ); | ||||||
|  | 			var turbulenceAttribute = this.particleShaderGeo.getAttribute( 'turbulence' ); | ||||||
|  | 			var colorAttribute = this.particleShaderGeo.getAttribute( 'color' ); | ||||||
|  | 			var sizeAttribute = this.particleShaderGeo.getAttribute( 'size' ); | ||||||
|  | 			var lifeTimeAttribute = this.particleShaderGeo.getAttribute( 'lifeTime' ); | ||||||
|  |  | ||||||
|  | 			if ( this.offset + this.count < this.PARTICLE_COUNT ) { | ||||||
|  |  | ||||||
|  | 				positionStartAttribute.updateRange.offset = this.offset * positionStartAttribute.itemSize; | ||||||
|  | 				startTimeAttribute.updateRange.offset = this.offset * startTimeAttribute.itemSize; | ||||||
|  | 				velocityAttribute.updateRange.offset = this.offset * velocityAttribute.itemSize; | ||||||
|  | 				turbulenceAttribute.updateRange.offset = this.offset * turbulenceAttribute.itemSize; | ||||||
|  | 				colorAttribute.updateRange.offset = this.offset * colorAttribute.itemSize; | ||||||
|  | 				sizeAttribute.updateRange.offset = this.offset * sizeAttribute.itemSize; | ||||||
|  | 				lifeTimeAttribute.updateRange.offset = this.offset * lifeTimeAttribute.itemSize; | ||||||
|  |  | ||||||
|  | 				positionStartAttribute.updateRange.count = this.count * positionStartAttribute.itemSize; | ||||||
|  | 				startTimeAttribute.updateRange.count = this.count * startTimeAttribute.itemSize; | ||||||
|  | 				velocityAttribute.updateRange.count = this.count * velocityAttribute.itemSize; | ||||||
|  | 				turbulenceAttribute.updateRange.count = this.count * turbulenceAttribute.itemSize; | ||||||
|  | 				colorAttribute.updateRange.count = this.count * colorAttribute.itemSize; | ||||||
|  | 				sizeAttribute.updateRange.count = this.count * sizeAttribute.itemSize; | ||||||
|  | 				lifeTimeAttribute.updateRange.count = this.count * lifeTimeAttribute.itemSize; | ||||||
|  |  | ||||||
|  | 			} else { | ||||||
|  |  | ||||||
|  | 				positionStartAttribute.updateRange.offset = 0; | ||||||
|  | 				startTimeAttribute.updateRange.offset = 0; | ||||||
|  | 				velocityAttribute.updateRange.offset = 0; | ||||||
|  | 				turbulenceAttribute.updateRange.offset = 0; | ||||||
|  | 				colorAttribute.updateRange.offset = 0; | ||||||
|  | 				sizeAttribute.updateRange.offset = 0; | ||||||
|  | 				lifeTimeAttribute.updateRange.offset = 0; | ||||||
|  |  | ||||||
|  | 				// Use -1 to update the entire buffer, see #11476 | ||||||
|  | 				positionStartAttribute.updateRange.count = -1; | ||||||
|  | 				startTimeAttribute.updateRange.count = -1; | ||||||
|  | 				velocityAttribute.updateRange.count = -1; | ||||||
|  | 				turbulenceAttribute.updateRange.count = -1; | ||||||
|  | 				colorAttribute.updateRange.count = -1; | ||||||
|  | 				sizeAttribute.updateRange.count = -1; | ||||||
|  | 				lifeTimeAttribute.updateRange.count = -1; | ||||||
|  |  | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			positionStartAttribute.needsUpdate = true; | ||||||
|  | 			startTimeAttribute.needsUpdate = true; | ||||||
|  | 			velocityAttribute.needsUpdate = true; | ||||||
|  | 			turbulenceAttribute.needsUpdate = true; | ||||||
|  | 			colorAttribute.needsUpdate = true; | ||||||
|  | 			sizeAttribute.needsUpdate = true; | ||||||
|  | 			lifeTimeAttribute.needsUpdate = true; | ||||||
|  |  | ||||||
|  | 			this.offset = 0; | ||||||
|  | 			this.count = 0; | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	this.dispose = function() { | ||||||
|  |  | ||||||
|  | 		this.particleShaderGeo.dispose(); | ||||||
|  |  | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	this.init(); | ||||||
|  |  | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | THREE.GPUParticleContainer.prototype = Object.create( THREE.Object3D.prototype ); | ||||||
|  | THREE.GPUParticleContainer.prototype.constructor = THREE.GPUParticleContainer; | ||||||
							
								
								
									
										551
									
								
								static/pkg/solar/js/libs/MTLLoader.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,551 @@ | |||||||
|  | /** | ||||||
|  |  * Loads a Wavefront .mtl file specifying materials | ||||||
|  |  * | ||||||
|  |  * @author angelxuanchang | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | THREE.MTLLoader = function ( manager ) { | ||||||
|  |  | ||||||
|  | 	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; | ||||||
|  |  | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | THREE.MTLLoader.prototype = { | ||||||
|  |  | ||||||
|  | 	constructor: THREE.MTLLoader, | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Loads and parses a MTL asset from a URL. | ||||||
|  | 	 * | ||||||
|  | 	 * @param {String} url - URL to the MTL file. | ||||||
|  | 	 * @param {Function} [onLoad] - Callback invoked with the loaded object. | ||||||
|  | 	 * @param {Function} [onProgress] - Callback for download progress. | ||||||
|  | 	 * @param {Function} [onError] - Callback for download errors. | ||||||
|  | 	 * | ||||||
|  | 	 * @see setPath setTexturePath | ||||||
|  | 	 * | ||||||
|  | 	 * @note In order for relative texture references to resolve correctly | ||||||
|  | 	 * you must call setPath and/or setTexturePath explicitly prior to load. | ||||||
|  | 	 */ | ||||||
|  | 	load: function ( url, onLoad, onProgress, onError ) { | ||||||
|  |  | ||||||
|  | 		var scope = this; | ||||||
|  |  | ||||||
|  | 		var loader = new THREE.FileLoader( this.manager ); | ||||||
|  | 		loader.setPath( this.path ); | ||||||
|  | 		loader.load( url, function ( text ) { | ||||||
|  |  | ||||||
|  | 			onLoad( scope.parse( text ) ); | ||||||
|  |  | ||||||
|  | 		}, onProgress, onError ); | ||||||
|  |  | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Set base path for resolving references. | ||||||
|  | 	 * If set this path will be prepended to each loaded and found reference. | ||||||
|  | 	 * | ||||||
|  | 	 * @see setTexturePath | ||||||
|  | 	 * @param {String} path | ||||||
|  | 	 * | ||||||
|  | 	 * @example | ||||||
|  | 	 *     mtlLoader.setPath( 'assets/obj/' ); | ||||||
|  | 	 *     mtlLoader.load( 'my.mtl', ... ); | ||||||
|  | 	 */ | ||||||
|  | 	setPath: function ( path ) { | ||||||
|  |  | ||||||
|  | 		this.path = path; | ||||||
|  |  | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Set base path for resolving texture references. | ||||||
|  | 	 * If set this path will be prepended found texture reference. | ||||||
|  | 	 * If not set and setPath is, it will be used as texture base path. | ||||||
|  | 	 * | ||||||
|  | 	 * @see setPath | ||||||
|  | 	 * @param {String} path | ||||||
|  | 	 * | ||||||
|  | 	 * @example | ||||||
|  | 	 *     mtlLoader.setPath( 'assets/obj/' ); | ||||||
|  | 	 *     mtlLoader.setTexturePath( 'assets/textures/' ); | ||||||
|  | 	 *     mtlLoader.load( 'my.mtl', ... ); | ||||||
|  | 	 */ | ||||||
|  | 	setTexturePath: function ( path ) { | ||||||
|  |  | ||||||
|  | 		this.texturePath = path; | ||||||
|  |  | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	setBaseUrl: function ( path ) { | ||||||
|  |  | ||||||
|  | 		console.warn( 'THREE.MTLLoader: .setBaseUrl() is deprecated. Use .setTexturePath( path ) for texture path or .setPath( path ) for general base path instead.' ); | ||||||
|  |  | ||||||
|  | 		this.setTexturePath( path ); | ||||||
|  |  | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	setCrossOrigin: function ( value ) { | ||||||
|  |  | ||||||
|  | 		this.crossOrigin = value; | ||||||
|  |  | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	setMaterialOptions: function ( value ) { | ||||||
|  |  | ||||||
|  | 		this.materialOptions = value; | ||||||
|  |  | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Parses a MTL file. | ||||||
|  | 	 * | ||||||
|  | 	 * @param {String} text - Content of MTL file | ||||||
|  | 	 * @return {THREE.MTLLoader.MaterialCreator} | ||||||
|  | 	 * | ||||||
|  | 	 * @see setPath setTexturePath | ||||||
|  | 	 * | ||||||
|  | 	 * @note In order for relative texture references to resolve correctly | ||||||
|  | 	 * you must call setPath and/or setTexturePath explicitly prior to parse. | ||||||
|  | 	 */ | ||||||
|  | 	parse: function ( text ) { | ||||||
|  |  | ||||||
|  | 		var lines = text.split( '\n' ); | ||||||
|  | 		var info = {}; | ||||||
|  | 		var delimiter_pattern = /\s+/; | ||||||
|  | 		var materialsInfo = {}; | ||||||
|  |  | ||||||
|  | 		for ( var i = 0; i < lines.length; i ++ ) { | ||||||
|  |  | ||||||
|  | 			var line = lines[ i ]; | ||||||
|  | 			line = line.trim(); | ||||||
|  |  | ||||||
|  | 			if ( line.length === 0 || line.charAt( 0 ) === '#' ) { | ||||||
|  |  | ||||||
|  | 				// Blank line or comment ignore | ||||||
|  | 				continue; | ||||||
|  |  | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			var pos = line.indexOf( ' ' ); | ||||||
|  |  | ||||||
|  | 			var key = ( pos >= 0 ) ? line.substring( 0, pos ) : line; | ||||||
|  | 			key = key.toLowerCase(); | ||||||
|  |  | ||||||
|  | 			var value = ( pos >= 0 ) ? line.substring( pos + 1 ) : ''; | ||||||
|  | 			value = value.trim(); | ||||||
|  |  | ||||||
|  | 			if ( key === 'newmtl' ) { | ||||||
|  |  | ||||||
|  | 				// New material | ||||||
|  |  | ||||||
|  | 				info = { name: value }; | ||||||
|  | 				materialsInfo[ value ] = info; | ||||||
|  |  | ||||||
|  | 			} else if ( info ) { | ||||||
|  |  | ||||||
|  | 				if ( key === 'ka' || key === 'kd' || key === 'ks' ) { | ||||||
|  |  | ||||||
|  | 					var ss = value.split( delimiter_pattern, 3 ); | ||||||
|  | 					info[ key ] = [ parseFloat( ss[ 0 ] ), parseFloat( ss[ 1 ] ), parseFloat( ss[ 2 ] ) ]; | ||||||
|  |  | ||||||
|  | 				} else { | ||||||
|  |  | ||||||
|  | 					info[ key ] = value; | ||||||
|  |  | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		var materialCreator = new THREE.MTLLoader.MaterialCreator( this.texturePath || this.path, this.materialOptions ); | ||||||
|  | 		materialCreator.setCrossOrigin( this.crossOrigin ); | ||||||
|  | 		materialCreator.setManager( this.manager ); | ||||||
|  | 		materialCreator.setMaterials( materialsInfo ); | ||||||
|  | 		return materialCreator; | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Create a new THREE-MTLLoader.MaterialCreator | ||||||
|  |  * @param baseUrl - Url relative to which textures are loaded | ||||||
|  |  * @param options - Set of options on how to construct the materials | ||||||
|  |  *                  side: Which side to apply the material | ||||||
|  |  *                        THREE.FrontSide (default), THREE.BackSide, THREE.DoubleSide | ||||||
|  |  *                  wrap: What type of wrapping to apply for textures | ||||||
|  |  *                        THREE.RepeatWrapping (default), THREE.ClampToEdgeWrapping, THREE.MirroredRepeatWrapping | ||||||
|  |  *                  normalizeRGB: RGBs need to be normalized to 0-1 from 0-255 | ||||||
|  |  *                                Default: false, assumed to be already normalized | ||||||
|  |  *                  ignoreZeroRGBs: Ignore values of RGBs (Ka,Kd,Ks) that are all 0's | ||||||
|  |  *                                  Default: false | ||||||
|  |  * @constructor | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | THREE.MTLLoader.MaterialCreator = function ( baseUrl, options ) { | ||||||
|  |  | ||||||
|  | 	this.baseUrl = baseUrl || ''; | ||||||
|  | 	this.options = options; | ||||||
|  | 	this.materialsInfo = {}; | ||||||
|  | 	this.materials = {}; | ||||||
|  | 	this.materialsArray = []; | ||||||
|  | 	this.nameLookup = {}; | ||||||
|  |  | ||||||
|  | 	this.side = ( this.options && this.options.side ) ? this.options.side : THREE.FrontSide; | ||||||
|  | 	this.wrap = ( this.options && this.options.wrap ) ? this.options.wrap : THREE.RepeatWrapping; | ||||||
|  |  | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | THREE.MTLLoader.MaterialCreator.prototype = { | ||||||
|  |  | ||||||
|  | 	constructor: THREE.MTLLoader.MaterialCreator, | ||||||
|  |  | ||||||
|  | 	crossOrigin: 'Anonymous', | ||||||
|  |  | ||||||
|  | 	setCrossOrigin: function ( value ) { | ||||||
|  |  | ||||||
|  | 		this.crossOrigin = value; | ||||||
|  |  | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	setManager: function ( value ) { | ||||||
|  |  | ||||||
|  | 		this.manager = value; | ||||||
|  |  | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	setMaterials: function ( materialsInfo ) { | ||||||
|  |  | ||||||
|  | 		this.materialsInfo = this.convert( materialsInfo ); | ||||||
|  | 		this.materials = {}; | ||||||
|  | 		this.materialsArray = []; | ||||||
|  | 		this.nameLookup = {}; | ||||||
|  |  | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	convert: function ( materialsInfo ) { | ||||||
|  |  | ||||||
|  | 		if ( ! this.options ) return materialsInfo; | ||||||
|  |  | ||||||
|  | 		var converted = {}; | ||||||
|  |  | ||||||
|  | 		for ( var mn in materialsInfo ) { | ||||||
|  |  | ||||||
|  | 			// Convert materials info into normalized form based on options | ||||||
|  |  | ||||||
|  | 			var mat = materialsInfo[ mn ]; | ||||||
|  |  | ||||||
|  | 			var covmat = {}; | ||||||
|  |  | ||||||
|  | 			converted[ mn ] = covmat; | ||||||
|  |  | ||||||
|  | 			for ( var prop in mat ) { | ||||||
|  |  | ||||||
|  | 				var save = true; | ||||||
|  | 				var value = mat[ prop ]; | ||||||
|  | 				var lprop = prop.toLowerCase(); | ||||||
|  |  | ||||||
|  | 				switch ( lprop ) { | ||||||
|  |  | ||||||
|  | 					case 'kd': | ||||||
|  | 					case 'ka': | ||||||
|  | 					case 'ks': | ||||||
|  |  | ||||||
|  | 						// Diffuse color (color under white light) using RGB values | ||||||
|  |  | ||||||
|  | 						if ( this.options && this.options.normalizeRGB ) { | ||||||
|  |  | ||||||
|  | 							value = [ value[ 0 ] / 255, value[ 1 ] / 255, value[ 2 ] / 255 ]; | ||||||
|  |  | ||||||
|  | 						} | ||||||
|  |  | ||||||
|  | 						if ( this.options && this.options.ignoreZeroRGBs ) { | ||||||
|  |  | ||||||
|  | 							if ( value[ 0 ] === 0 && value[ 1 ] === 0 && value[ 2 ] === 0 ) { | ||||||
|  |  | ||||||
|  | 								// ignore | ||||||
|  |  | ||||||
|  | 								save = false; | ||||||
|  |  | ||||||
|  | 							} | ||||||
|  |  | ||||||
|  | 						} | ||||||
|  |  | ||||||
|  | 						break; | ||||||
|  |  | ||||||
|  | 					default: | ||||||
|  |  | ||||||
|  | 						break; | ||||||
|  |  | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				if ( save ) { | ||||||
|  |  | ||||||
|  | 					covmat[ lprop ] = value; | ||||||
|  |  | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return converted; | ||||||
|  |  | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	preload: function () { | ||||||
|  |  | ||||||
|  | 		for ( var mn in this.materialsInfo ) { | ||||||
|  |  | ||||||
|  | 			this.create( mn ); | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	getIndex: function ( materialName ) { | ||||||
|  |  | ||||||
|  | 		return this.nameLookup[ materialName ]; | ||||||
|  |  | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	getAsArray: function () { | ||||||
|  |  | ||||||
|  | 		var index = 0; | ||||||
|  |  | ||||||
|  | 		for ( var mn in this.materialsInfo ) { | ||||||
|  |  | ||||||
|  | 			this.materialsArray[ index ] = this.create( mn ); | ||||||
|  | 			this.nameLookup[ mn ] = index; | ||||||
|  | 			index ++; | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return this.materialsArray; | ||||||
|  |  | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	create: function ( materialName ) { | ||||||
|  |  | ||||||
|  | 		if ( this.materials[ materialName ] === undefined ) { | ||||||
|  |  | ||||||
|  | 			this.createMaterial_( materialName ); | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return this.materials[ materialName ]; | ||||||
|  |  | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	createMaterial_: function ( materialName ) { | ||||||
|  |  | ||||||
|  | 		// Create material | ||||||
|  |  | ||||||
|  | 		var scope = this; | ||||||
|  | 		var mat = this.materialsInfo[ materialName ]; | ||||||
|  | 		var params = { | ||||||
|  |  | ||||||
|  | 			name: materialName, | ||||||
|  | 			side: this.side | ||||||
|  |  | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		function resolveURL( baseUrl, url ) { | ||||||
|  |  | ||||||
|  | 			if ( typeof url !== 'string' || url === '' ) | ||||||
|  | 				return ''; | ||||||
|  |  | ||||||
|  | 			// Absolute URL | ||||||
|  | 			if ( /^https?:\/\//i.test( url ) ) return url; | ||||||
|  |  | ||||||
|  | 			return baseUrl + url; | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		function setMapForType( mapType, value ) { | ||||||
|  |  | ||||||
|  | 			if ( params[ mapType ] ) return; // Keep the first encountered texture | ||||||
|  |  | ||||||
|  | 			var texParams = scope.getTextureParams( value, params ); | ||||||
|  | 			var map = scope.loadTexture( resolveURL( scope.baseUrl, texParams.url ) ); | ||||||
|  |  | ||||||
|  | 			map.repeat.copy( texParams.scale ); | ||||||
|  | 			map.offset.copy( texParams.offset ); | ||||||
|  |  | ||||||
|  | 			map.wrapS = scope.wrap; | ||||||
|  | 			map.wrapT = scope.wrap; | ||||||
|  |  | ||||||
|  | 			params[ mapType ] = map; | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		for ( var prop in mat ) { | ||||||
|  |  | ||||||
|  | 			var value = mat[ prop ]; | ||||||
|  | 			var n; | ||||||
|  |  | ||||||
|  | 			if ( value === '' ) continue; | ||||||
|  |  | ||||||
|  | 			switch ( prop.toLowerCase() ) { | ||||||
|  |  | ||||||
|  | 				// Ns is material specular exponent | ||||||
|  |  | ||||||
|  | 				case 'kd': | ||||||
|  |  | ||||||
|  | 					// Diffuse color (color under white light) using RGB values | ||||||
|  |  | ||||||
|  | 					params.color = new THREE.Color().fromArray( value ); | ||||||
|  |  | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				case 'ks': | ||||||
|  |  | ||||||
|  | 					// Specular color (color when light is reflected from shiny surface) using RGB values | ||||||
|  | 					params.specular = new THREE.Color().fromArray( value ); | ||||||
|  |  | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				case 'map_kd': | ||||||
|  |  | ||||||
|  | 					// Diffuse texture map | ||||||
|  |  | ||||||
|  | 					setMapForType( "map", value ); | ||||||
|  |  | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				case 'map_ks': | ||||||
|  |  | ||||||
|  | 					// Specular map | ||||||
|  |  | ||||||
|  | 					setMapForType( "specularMap", value ); | ||||||
|  |  | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				case 'norm': | ||||||
|  |  | ||||||
|  | 					setMapForType( "normalMap", value ); | ||||||
|  |  | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				case 'map_bump': | ||||||
|  | 				case 'bump': | ||||||
|  |  | ||||||
|  | 					// Bump texture map | ||||||
|  |  | ||||||
|  | 					setMapForType( "bumpMap", value ); | ||||||
|  |  | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				case 'ns': | ||||||
|  |  | ||||||
|  | 					// The specular exponent (defines the focus of the specular highlight) | ||||||
|  | 					// A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000. | ||||||
|  |  | ||||||
|  | 					params.shininess = parseFloat( value ); | ||||||
|  |  | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				case 'd': | ||||||
|  | 					n = parseFloat( value ); | ||||||
|  |  | ||||||
|  | 					if ( n < 1 ) { | ||||||
|  |  | ||||||
|  | 						params.opacity = n; | ||||||
|  | 						params.transparent = true; | ||||||
|  |  | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				case 'tr': | ||||||
|  | 					n = parseFloat( value ); | ||||||
|  |  | ||||||
|  | 					if ( n > 0 ) { | ||||||
|  |  | ||||||
|  | 						params.opacity = 1 - n; | ||||||
|  | 						params.transparent = true; | ||||||
|  |  | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				default: | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		this.materials[ materialName ] = new THREE.MeshPhongMaterial( params ); | ||||||
|  | 		return this.materials[ materialName ]; | ||||||
|  |  | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	getTextureParams: function ( value, matParams ) { | ||||||
|  |  | ||||||
|  | 		var texParams = { | ||||||
|  |  | ||||||
|  | 			scale: new THREE.Vector2( 1, 1 ), | ||||||
|  | 			offset: new THREE.Vector2( 0, 0 ) | ||||||
|  |  | ||||||
|  | 		 }; | ||||||
|  |  | ||||||
|  | 		var items = value.split( /\s+/ ); | ||||||
|  | 		var pos; | ||||||
|  |  | ||||||
|  | 		pos = items.indexOf( '-bm' ); | ||||||
|  |  | ||||||
|  | 		if ( pos >= 0 ) { | ||||||
|  |  | ||||||
|  | 			matParams.bumpScale = parseFloat( items[ pos + 1 ] ); | ||||||
|  | 			items.splice( pos, 2 ); | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		pos = items.indexOf( '-s' ); | ||||||
|  |  | ||||||
|  | 		if ( pos >= 0 ) { | ||||||
|  |  | ||||||
|  | 			texParams.scale.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) ); | ||||||
|  | 			items.splice( pos, 4 ); // we expect 3 parameters here! | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		pos = items.indexOf( '-o' ); | ||||||
|  |  | ||||||
|  | 		if ( pos >= 0 ) { | ||||||
|  |  | ||||||
|  | 			texParams.offset.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) ); | ||||||
|  | 			items.splice( pos, 4 ); // we expect 3 parameters here! | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		texParams.url = items.join( ' ' ).trim(); | ||||||
|  | 		return texParams; | ||||||
|  |  | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	loadTexture: function ( url, mapping, onLoad, onProgress, onError ) { | ||||||
|  |  | ||||||
|  | 		var texture; | ||||||
|  | 		var loader = THREE.Loader.Handlers.get( url ); | ||||||
|  | 		var manager = ( this.manager !== undefined ) ? this.manager : THREE.DefaultLoadingManager; | ||||||
|  |  | ||||||
|  | 		if ( loader === null ) { | ||||||
|  |  | ||||||
|  | 			loader = new THREE.TextureLoader( manager ); | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if ( loader.setCrossOrigin ) loader.setCrossOrigin( this.crossOrigin ); | ||||||
|  | 		texture = loader.load( url, onLoad, onProgress, onError ); | ||||||
|  |  | ||||||
|  | 		if ( mapping !== undefined ) texture.mapping = mapping; | ||||||
|  |  | ||||||
|  | 		return texture; | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | }; | ||||||
							
								
								
									
										715
									
								
								static/pkg/solar/js/libs/OBJLoader.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,715 @@ | |||||||
|  | /** | ||||||
|  |  * @author mrdoob / http://mrdoob.com/ | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | THREE.OBJLoader = ( function () { | ||||||
|  |  | ||||||
|  | 	// o object_name | g group_name | ||||||
|  | 	var object_pattern = /^[og]\s*(.+)?/; | ||||||
|  | 	// mtllib file_reference | ||||||
|  | 	var material_library_pattern = /^mtllib /; | ||||||
|  | 	// usemtl material_name | ||||||
|  | 	var material_use_pattern = /^usemtl /; | ||||||
|  |  | ||||||
|  | 	function ParserState() { | ||||||
|  |  | ||||||
|  | 		var state = { | ||||||
|  | 			objects: [], | ||||||
|  | 			object: {}, | ||||||
|  |  | ||||||
|  | 			vertices: [], | ||||||
|  | 			normals: [], | ||||||
|  | 			colors: [], | ||||||
|  | 			uvs: [], | ||||||
|  |  | ||||||
|  | 			materialLibraries: [], | ||||||
|  |  | ||||||
|  | 			startObject: function ( name, fromDeclaration ) { | ||||||
|  |  | ||||||
|  | 				// If the current object (initial from reset) is not from a g/o declaration in the parsed | ||||||
|  | 				// file. We need to use it for the first parsed g/o to keep things in sync. | ||||||
|  | 				if ( this.object && this.object.fromDeclaration === false ) { | ||||||
|  |  | ||||||
|  | 					this.object.name = name; | ||||||
|  | 					this.object.fromDeclaration = ( fromDeclaration !== false ); | ||||||
|  | 					return; | ||||||
|  |  | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				var previousMaterial = ( this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined ); | ||||||
|  |  | ||||||
|  | 				if ( this.object && typeof this.object._finalize === 'function' ) { | ||||||
|  |  | ||||||
|  | 					this.object._finalize( true ); | ||||||
|  |  | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				this.object = { | ||||||
|  | 					name: name || '', | ||||||
|  | 					fromDeclaration: ( fromDeclaration !== false ), | ||||||
|  |  | ||||||
|  | 					geometry: { | ||||||
|  | 						vertices: [], | ||||||
|  | 						normals: [], | ||||||
|  | 						colors: [], | ||||||
|  | 						uvs: [] | ||||||
|  | 					}, | ||||||
|  | 					materials: [], | ||||||
|  | 					smooth: true, | ||||||
|  |  | ||||||
|  | 					startMaterial: function ( name, libraries ) { | ||||||
|  |  | ||||||
|  | 						var previous = this._finalize( false ); | ||||||
|  |  | ||||||
|  | 						// New usemtl declaration overwrites an inherited material, except if faces were declared | ||||||
|  | 						// after the material, then it must be preserved for proper MultiMaterial continuation. | ||||||
|  | 						if ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) { | ||||||
|  |  | ||||||
|  | 							this.materials.splice( previous.index, 1 ); | ||||||
|  |  | ||||||
|  | 						} | ||||||
|  |  | ||||||
|  | 						var material = { | ||||||
|  | 							index: this.materials.length, | ||||||
|  | 							name: name || '', | ||||||
|  | 							mtllib: ( Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '' ), | ||||||
|  | 							smooth: ( previous !== undefined ? previous.smooth : this.smooth ), | ||||||
|  | 							groupStart: ( previous !== undefined ? previous.groupEnd : 0 ), | ||||||
|  | 							groupEnd: - 1, | ||||||
|  | 							groupCount: - 1, | ||||||
|  | 							inherited: false, | ||||||
|  |  | ||||||
|  | 							clone: function ( index ) { | ||||||
|  |  | ||||||
|  | 								var cloned = { | ||||||
|  | 									index: ( typeof index === 'number' ? index : this.index ), | ||||||
|  | 									name: this.name, | ||||||
|  | 									mtllib: this.mtllib, | ||||||
|  | 									smooth: this.smooth, | ||||||
|  | 									groupStart: 0, | ||||||
|  | 									groupEnd: - 1, | ||||||
|  | 									groupCount: - 1, | ||||||
|  | 									inherited: false | ||||||
|  | 								}; | ||||||
|  | 								cloned.clone = this.clone.bind( cloned ); | ||||||
|  | 								return cloned; | ||||||
|  |  | ||||||
|  | 							} | ||||||
|  | 						}; | ||||||
|  |  | ||||||
|  | 						this.materials.push( material ); | ||||||
|  |  | ||||||
|  | 						return material; | ||||||
|  |  | ||||||
|  | 					}, | ||||||
|  |  | ||||||
|  | 					currentMaterial: function () { | ||||||
|  |  | ||||||
|  | 						if ( this.materials.length > 0 ) { | ||||||
|  |  | ||||||
|  | 							return this.materials[ this.materials.length - 1 ]; | ||||||
|  |  | ||||||
|  | 						} | ||||||
|  |  | ||||||
|  | 						return undefined; | ||||||
|  |  | ||||||
|  | 					}, | ||||||
|  |  | ||||||
|  | 					_finalize: function ( end ) { | ||||||
|  |  | ||||||
|  | 						var lastMultiMaterial = this.currentMaterial(); | ||||||
|  | 						if ( lastMultiMaterial && lastMultiMaterial.groupEnd === - 1 ) { | ||||||
|  |  | ||||||
|  | 							lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3; | ||||||
|  | 							lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart; | ||||||
|  | 							lastMultiMaterial.inherited = false; | ||||||
|  |  | ||||||
|  | 						} | ||||||
|  |  | ||||||
|  | 						// Ignore objects tail materials if no face declarations followed them before a new o/g started. | ||||||
|  | 						if ( end && this.materials.length > 1 ) { | ||||||
|  |  | ||||||
|  | 							for ( var mi = this.materials.length - 1; mi >= 0; mi -- ) { | ||||||
|  |  | ||||||
|  | 								if ( this.materials[ mi ].groupCount <= 0 ) { | ||||||
|  |  | ||||||
|  | 									this.materials.splice( mi, 1 ); | ||||||
|  |  | ||||||
|  | 								} | ||||||
|  |  | ||||||
|  | 							} | ||||||
|  |  | ||||||
|  | 						} | ||||||
|  |  | ||||||
|  | 						// Guarantee at least one empty material, this makes the creation later more straight forward. | ||||||
|  | 						if ( end && this.materials.length === 0 ) { | ||||||
|  |  | ||||||
|  | 							this.materials.push( { | ||||||
|  | 								name: '', | ||||||
|  | 								smooth: this.smooth | ||||||
|  | 							} ); | ||||||
|  |  | ||||||
|  | 						} | ||||||
|  |  | ||||||
|  | 						return lastMultiMaterial; | ||||||
|  |  | ||||||
|  | 					} | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				// Inherit previous objects material. | ||||||
|  | 				// Spec tells us that a declared material must be set to all objects until a new material is declared. | ||||||
|  | 				// If a usemtl declaration is encountered while this new object is being parsed, it will | ||||||
|  | 				// overwrite the inherited material. Exception being that there was already face declarations | ||||||
|  | 				// to the inherited material, then it will be preserved for proper MultiMaterial continuation. | ||||||
|  |  | ||||||
|  | 				if ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function' ) { | ||||||
|  |  | ||||||
|  | 					var declared = previousMaterial.clone( 0 ); | ||||||
|  | 					declared.inherited = true; | ||||||
|  | 					this.object.materials.push( declared ); | ||||||
|  |  | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				this.objects.push( this.object ); | ||||||
|  |  | ||||||
|  | 			}, | ||||||
|  |  | ||||||
|  | 			finalize: function () { | ||||||
|  |  | ||||||
|  | 				if ( this.object && typeof this.object._finalize === 'function' ) { | ||||||
|  |  | ||||||
|  | 					this.object._finalize( true ); | ||||||
|  |  | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 			}, | ||||||
|  |  | ||||||
|  | 			parseVertexIndex: function ( value, len ) { | ||||||
|  |  | ||||||
|  | 				var index = parseInt( value, 10 ); | ||||||
|  | 				return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; | ||||||
|  |  | ||||||
|  | 			}, | ||||||
|  |  | ||||||
|  | 			parseNormalIndex: function ( value, len ) { | ||||||
|  |  | ||||||
|  | 				var index = parseInt( value, 10 ); | ||||||
|  | 				return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; | ||||||
|  |  | ||||||
|  | 			}, | ||||||
|  |  | ||||||
|  | 			parseUVIndex: function ( value, len ) { | ||||||
|  |  | ||||||
|  | 				var index = parseInt( value, 10 ); | ||||||
|  | 				return ( index >= 0 ? index - 1 : index + len / 2 ) * 2; | ||||||
|  |  | ||||||
|  | 			}, | ||||||
|  |  | ||||||
|  | 			addVertex: function ( a, b, c ) { | ||||||
|  |  | ||||||
|  | 				var src = this.vertices; | ||||||
|  | 				var dst = this.object.geometry.vertices; | ||||||
|  |  | ||||||
|  | 				dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); | ||||||
|  | 				dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); | ||||||
|  | 				dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); | ||||||
|  |  | ||||||
|  | 			}, | ||||||
|  |  | ||||||
|  | 			addVertexLine: function ( a ) { | ||||||
|  |  | ||||||
|  | 				var src = this.vertices; | ||||||
|  | 				var dst = this.object.geometry.vertices; | ||||||
|  |  | ||||||
|  | 				dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); | ||||||
|  |  | ||||||
|  | 			}, | ||||||
|  |  | ||||||
|  | 			addNormal: function ( a, b, c ) { | ||||||
|  |  | ||||||
|  | 				var src = this.normals; | ||||||
|  | 				var dst = this.object.geometry.normals; | ||||||
|  |  | ||||||
|  | 				dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); | ||||||
|  | 				dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); | ||||||
|  | 				dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); | ||||||
|  |  | ||||||
|  | 			}, | ||||||
|  |  | ||||||
|  | 			addColor: function ( a, b, c ) { | ||||||
|  |  | ||||||
|  | 				var src = this.colors; | ||||||
|  | 				var dst = this.object.geometry.colors; | ||||||
|  |  | ||||||
|  | 				dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); | ||||||
|  | 				dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); | ||||||
|  | 				dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); | ||||||
|  |  | ||||||
|  | 			}, | ||||||
|  |  | ||||||
|  | 			addUV: function ( a, b, c ) { | ||||||
|  |  | ||||||
|  | 				var src = this.uvs; | ||||||
|  | 				var dst = this.object.geometry.uvs; | ||||||
|  |  | ||||||
|  | 				dst.push( src[ a + 0 ], src[ a + 1 ] ); | ||||||
|  | 				dst.push( src[ b + 0 ], src[ b + 1 ] ); | ||||||
|  | 				dst.push( src[ c + 0 ], src[ c + 1 ] ); | ||||||
|  |  | ||||||
|  | 			}, | ||||||
|  |  | ||||||
|  | 			addUVLine: function ( a ) { | ||||||
|  |  | ||||||
|  | 				var src = this.uvs; | ||||||
|  | 				var dst = this.object.geometry.uvs; | ||||||
|  |  | ||||||
|  | 				dst.push( src[ a + 0 ], src[ a + 1 ] ); | ||||||
|  |  | ||||||
|  | 			}, | ||||||
|  |  | ||||||
|  | 			addFace: function ( a, b, c, ua, ub, uc, na, nb, nc ) { | ||||||
|  |  | ||||||
|  | 				var vLen = this.vertices.length; | ||||||
|  |  | ||||||
|  | 				var ia = this.parseVertexIndex( a, vLen ); | ||||||
|  | 				var ib = this.parseVertexIndex( b, vLen ); | ||||||
|  | 				var ic = this.parseVertexIndex( c, vLen ); | ||||||
|  |  | ||||||
|  | 				this.addVertex( ia, ib, ic ); | ||||||
|  |  | ||||||
|  | 				if ( ua !== undefined ) { | ||||||
|  |  | ||||||
|  | 					var uvLen = this.uvs.length; | ||||||
|  |  | ||||||
|  | 					ia = this.parseUVIndex( ua, uvLen ); | ||||||
|  | 					ib = this.parseUVIndex( ub, uvLen ); | ||||||
|  | 					ic = this.parseUVIndex( uc, uvLen ); | ||||||
|  |  | ||||||
|  | 					this.addUV( ia, ib, ic ); | ||||||
|  |  | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				if ( na !== undefined ) { | ||||||
|  |  | ||||||
|  | 					// Normals are many times the same. If so, skip function call and parseInt. | ||||||
|  | 					var nLen = this.normals.length; | ||||||
|  | 					ia = this.parseNormalIndex( na, nLen ); | ||||||
|  |  | ||||||
|  | 					ib = na === nb ? ia : this.parseNormalIndex( nb, nLen ); | ||||||
|  | 					ic = na === nc ? ia : this.parseNormalIndex( nc, nLen ); | ||||||
|  |  | ||||||
|  | 					this.addNormal( ia, ib, ic ); | ||||||
|  |  | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				if ( this.colors.length > 0 ) { | ||||||
|  |  | ||||||
|  | 					this.addColor( ia, ib, ic ); | ||||||
|  |  | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 			}, | ||||||
|  |  | ||||||
|  | 			addLineGeometry: function ( vertices, uvs ) { | ||||||
|  |  | ||||||
|  | 				this.object.geometry.type = 'Line'; | ||||||
|  |  | ||||||
|  | 				var vLen = this.vertices.length; | ||||||
|  | 				var uvLen = this.uvs.length; | ||||||
|  |  | ||||||
|  | 				for ( var vi = 0, l = vertices.length; vi < l; vi ++ ) { | ||||||
|  |  | ||||||
|  | 					this.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) ); | ||||||
|  |  | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				for ( var uvi = 0, l = uvs.length; uvi < l; uvi ++ ) { | ||||||
|  |  | ||||||
|  | 					this.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) ); | ||||||
|  |  | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		state.startObject( '', false ); | ||||||
|  |  | ||||||
|  | 		return state; | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// | ||||||
|  |  | ||||||
|  | 	function OBJLoader( manager ) { | ||||||
|  |  | ||||||
|  | 		this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; | ||||||
|  |  | ||||||
|  | 		this.materials = null; | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	OBJLoader.prototype = { | ||||||
|  |  | ||||||
|  | 		constructor: OBJLoader, | ||||||
|  |  | ||||||
|  | 		load: function ( url, onLoad, onProgress, onError ) { | ||||||
|  |  | ||||||
|  | 			var scope = this; | ||||||
|  |  | ||||||
|  | 			var loader = new THREE.FileLoader( scope.manager ); | ||||||
|  | 			loader.setPath( this.path ); | ||||||
|  | 			loader.load( url, function ( text ) { | ||||||
|  |  | ||||||
|  | 				onLoad( scope.parse( text ) ); | ||||||
|  |  | ||||||
|  | 			}, onProgress, onError ); | ||||||
|  |  | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		setPath: function ( value ) { | ||||||
|  |  | ||||||
|  | 			this.path = value; | ||||||
|  |  | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		setMaterials: function ( materials ) { | ||||||
|  |  | ||||||
|  | 			this.materials = materials; | ||||||
|  |  | ||||||
|  | 			return this; | ||||||
|  |  | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		parse: function ( text ) { | ||||||
|  |  | ||||||
|  | 			console.time( 'OBJLoader' ); | ||||||
|  |  | ||||||
|  | 			var state = new ParserState(); | ||||||
|  |  | ||||||
|  | 			if ( text.indexOf( '\r\n' ) !== - 1 ) { | ||||||
|  |  | ||||||
|  | 				// This is faster than String.split with regex that splits on both | ||||||
|  | 				text = text.replace( /\r\n/g, '\n' ); | ||||||
|  |  | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if ( text.indexOf( '\\\n' ) !== - 1 ) { | ||||||
|  |  | ||||||
|  | 				// join lines separated by a line continuation character (\) | ||||||
|  | 				text = text.replace( /\\\n/g, '' ); | ||||||
|  |  | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			var lines = text.split( '\n' ); | ||||||
|  | 			var line = '', lineFirstChar = ''; | ||||||
|  | 			var lineLength = 0; | ||||||
|  | 			var result = []; | ||||||
|  |  | ||||||
|  | 			// Faster to just trim left side of the line. Use if available. | ||||||
|  | 			var trimLeft = ( typeof ''.trimLeft === 'function' ); | ||||||
|  |  | ||||||
|  | 			for ( var i = 0, l = lines.length; i < l; i ++ ) { | ||||||
|  |  | ||||||
|  | 				line = lines[ i ]; | ||||||
|  |  | ||||||
|  | 				line = trimLeft ? line.trimLeft() : line.trim(); | ||||||
|  |  | ||||||
|  | 				lineLength = line.length; | ||||||
|  |  | ||||||
|  | 				if ( lineLength === 0 ) continue; | ||||||
|  |  | ||||||
|  | 				lineFirstChar = line.charAt( 0 ); | ||||||
|  |  | ||||||
|  | 				// @todo invoke passed in handler if any | ||||||
|  | 				if ( lineFirstChar === '#' ) continue; | ||||||
|  |  | ||||||
|  | 				if ( lineFirstChar === 'v' ) { | ||||||
|  |  | ||||||
|  | 					var data = line.split( /\s+/ ); | ||||||
|  |  | ||||||
|  | 					switch ( data[ 0 ] ) { | ||||||
|  |  | ||||||
|  | 						case 'v': | ||||||
|  | 							state.vertices.push( | ||||||
|  | 								parseFloat( data[ 1 ] ), | ||||||
|  | 								parseFloat( data[ 2 ] ), | ||||||
|  | 								parseFloat( data[ 3 ] ) | ||||||
|  | 							); | ||||||
|  | 							if ( data.length === 8 ) { | ||||||
|  |  | ||||||
|  | 								state.colors.push( | ||||||
|  | 									parseFloat( data[ 4 ] ), | ||||||
|  | 									parseFloat( data[ 5 ] ), | ||||||
|  | 									parseFloat( data[ 6 ] ) | ||||||
|  |  | ||||||
|  | 								); | ||||||
|  |  | ||||||
|  | 							} | ||||||
|  | 							break; | ||||||
|  | 						case 'vn': | ||||||
|  | 							state.normals.push( | ||||||
|  | 								parseFloat( data[ 1 ] ), | ||||||
|  | 								parseFloat( data[ 2 ] ), | ||||||
|  | 								parseFloat( data[ 3 ] ) | ||||||
|  | 							); | ||||||
|  | 							break; | ||||||
|  | 						case 'vt': | ||||||
|  | 							state.uvs.push( | ||||||
|  | 								parseFloat( data[ 1 ] ), | ||||||
|  | 								parseFloat( data[ 2 ] ) | ||||||
|  | 							); | ||||||
|  | 							break; | ||||||
|  |  | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 				} else if ( lineFirstChar === 'f' ) { | ||||||
|  |  | ||||||
|  | 					var lineData = line.substr( 1 ).trim(); | ||||||
|  | 					var vertexData = lineData.split( /\s+/ ); | ||||||
|  | 					var faceVertices = []; | ||||||
|  |  | ||||||
|  | 					// Parse the face vertex data into an easy to work with format | ||||||
|  |  | ||||||
|  | 					for ( var j = 0, jl = vertexData.length; j < jl; j ++ ) { | ||||||
|  |  | ||||||
|  | 						var vertex = vertexData[ j ]; | ||||||
|  |  | ||||||
|  | 						if ( vertex.length > 0 ) { | ||||||
|  |  | ||||||
|  | 							var vertexParts = vertex.split( '/' ); | ||||||
|  | 							faceVertices.push( vertexParts ); | ||||||
|  |  | ||||||
|  | 						} | ||||||
|  |  | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 					// Draw an edge between the first vertex and all subsequent vertices to form an n-gon | ||||||
|  |  | ||||||
|  | 					var v1 = faceVertices[ 0 ]; | ||||||
|  |  | ||||||
|  | 					for ( var j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) { | ||||||
|  |  | ||||||
|  | 						var v2 = faceVertices[ j ]; | ||||||
|  | 						var v3 = faceVertices[ j + 1 ]; | ||||||
|  |  | ||||||
|  | 						state.addFace( | ||||||
|  | 							v1[ 0 ], v2[ 0 ], v3[ 0 ], | ||||||
|  | 							v1[ 1 ], v2[ 1 ], v3[ 1 ], | ||||||
|  | 							v1[ 2 ], v2[ 2 ], v3[ 2 ] | ||||||
|  | 						); | ||||||
|  |  | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 				} else if ( lineFirstChar === 'l' ) { | ||||||
|  |  | ||||||
|  | 					var lineParts = line.substring( 1 ).trim().split( " " ); | ||||||
|  | 					var lineVertices = [], lineUVs = []; | ||||||
|  |  | ||||||
|  | 					if ( line.indexOf( "/" ) === - 1 ) { | ||||||
|  |  | ||||||
|  | 						lineVertices = lineParts; | ||||||
|  |  | ||||||
|  | 					} else { | ||||||
|  |  | ||||||
|  | 						for ( var li = 0, llen = lineParts.length; li < llen; li ++ ) { | ||||||
|  |  | ||||||
|  | 							var parts = lineParts[ li ].split( "/" ); | ||||||
|  |  | ||||||
|  | 							if ( parts[ 0 ] !== "" ) lineVertices.push( parts[ 0 ] ); | ||||||
|  | 							if ( parts[ 1 ] !== "" ) lineUVs.push( parts[ 1 ] ); | ||||||
|  |  | ||||||
|  | 						} | ||||||
|  |  | ||||||
|  | 					} | ||||||
|  | 					state.addLineGeometry( lineVertices, lineUVs ); | ||||||
|  |  | ||||||
|  | 				} else if ( ( result = object_pattern.exec( line ) ) !== null ) { | ||||||
|  |  | ||||||
|  | 					// o object_name | ||||||
|  | 					// or | ||||||
|  | 					// g group_name | ||||||
|  |  | ||||||
|  | 					// WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869 | ||||||
|  | 					// var name = result[ 0 ].substr( 1 ).trim(); | ||||||
|  | 					var name = ( " " + result[ 0 ].substr( 1 ).trim() ).substr( 1 ); | ||||||
|  |  | ||||||
|  | 					state.startObject( name ); | ||||||
|  |  | ||||||
|  | 				} else if ( material_use_pattern.test( line ) ) { | ||||||
|  |  | ||||||
|  | 					// material | ||||||
|  |  | ||||||
|  | 					state.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries ); | ||||||
|  |  | ||||||
|  | 				} else if ( material_library_pattern.test( line ) ) { | ||||||
|  |  | ||||||
|  | 					// mtl file | ||||||
|  |  | ||||||
|  | 					state.materialLibraries.push( line.substring( 7 ).trim() ); | ||||||
|  |  | ||||||
|  | 				} else if ( lineFirstChar === 's' ) { | ||||||
|  |  | ||||||
|  | 					result = line.split( ' ' ); | ||||||
|  |  | ||||||
|  | 					// smooth shading | ||||||
|  |  | ||||||
|  | 					// @todo Handle files that have varying smooth values for a set of faces inside one geometry, | ||||||
|  | 					// but does not define a usemtl for each face set. | ||||||
|  | 					// This should be detected and a dummy material created (later MultiMaterial and geometry groups). | ||||||
|  | 					// This requires some care to not create extra material on each smooth value for "normal" obj files. | ||||||
|  | 					// where explicit usemtl defines geometry groups. | ||||||
|  | 					// Example asset: examples/models/obj/cerberus/Cerberus.obj | ||||||
|  |  | ||||||
|  | 					/* | ||||||
|  | 					 * http://paulbourke.net/dataformats/obj/ | ||||||
|  | 					 * or | ||||||
|  | 					 * http://www.cs.utah.edu/~boulos/cs3505/obj_spec.pdf | ||||||
|  | 					 * | ||||||
|  | 					 * From chapter "Grouping" Syntax explanation "s group_number": | ||||||
|  | 					 * "group_number is the smoothing group number. To turn off smoothing groups, use a value of 0 or off. | ||||||
|  | 					 * Polygonal elements use group numbers to put elements in different smoothing groups. For free-form | ||||||
|  | 					 * surfaces, smoothing groups are either turned on or off; there is no difference between values greater | ||||||
|  | 					 * than 0." | ||||||
|  | 					 */ | ||||||
|  | 					if ( result.length > 1 ) { | ||||||
|  |  | ||||||
|  | 						var value = result[ 1 ].trim().toLowerCase(); | ||||||
|  | 						state.object.smooth = ( value !== '0' && value !== 'off' ); | ||||||
|  |  | ||||||
|  | 					} else { | ||||||
|  |  | ||||||
|  | 						// ZBrush can produce "s" lines #11707 | ||||||
|  | 						state.object.smooth = true; | ||||||
|  |  | ||||||
|  | 					} | ||||||
|  | 					var material = state.object.currentMaterial(); | ||||||
|  | 					if ( material ) material.smooth = state.object.smooth; | ||||||
|  |  | ||||||
|  | 				} else { | ||||||
|  |  | ||||||
|  | 					// Handle null terminated files without exception | ||||||
|  | 					if ( line === '\0' ) continue; | ||||||
|  |  | ||||||
|  | 					throw new Error( 'THREE.OBJLoader: Unexpected line: "' + line + '"' ); | ||||||
|  |  | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			state.finalize(); | ||||||
|  |  | ||||||
|  | 			var container = new THREE.Group(); | ||||||
|  | 			container.materialLibraries = [].concat( state.materialLibraries ); | ||||||
|  |  | ||||||
|  | 			for ( var i = 0, l = state.objects.length; i < l; i ++ ) { | ||||||
|  |  | ||||||
|  | 				var object = state.objects[ i ]; | ||||||
|  | 				var geometry = object.geometry; | ||||||
|  | 				var materials = object.materials; | ||||||
|  | 				var isLine = ( geometry.type === 'Line' ); | ||||||
|  |  | ||||||
|  | 				// Skip o/g line declarations that did not follow with any faces | ||||||
|  | 				if ( geometry.vertices.length === 0 ) continue; | ||||||
|  |  | ||||||
|  | 				var buffergeometry = new THREE.BufferGeometry(); | ||||||
|  |  | ||||||
|  | 				buffergeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( geometry.vertices, 3 ) ); | ||||||
|  |  | ||||||
|  | 				if ( geometry.normals.length > 0 ) { | ||||||
|  |  | ||||||
|  | 					buffergeometry.addAttribute( 'normal', new THREE.Float32BufferAttribute( geometry.normals, 3 ) ); | ||||||
|  |  | ||||||
|  | 				} else { | ||||||
|  |  | ||||||
|  | 					buffergeometry.computeVertexNormals(); | ||||||
|  |  | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				if ( geometry.colors.length > 0 ) { | ||||||
|  |  | ||||||
|  | 					buffergeometry.addAttribute( 'color', new THREE.Float32BufferAttribute( geometry.colors, 3 ) ); | ||||||
|  |  | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				if ( geometry.uvs.length > 0 ) { | ||||||
|  |  | ||||||
|  | 					buffergeometry.addAttribute( 'uv', new THREE.Float32BufferAttribute( geometry.uvs, 2 ) ); | ||||||
|  |  | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				// Create materials | ||||||
|  |  | ||||||
|  | 				var createdMaterials = []; | ||||||
|  |  | ||||||
|  | 				for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { | ||||||
|  |  | ||||||
|  | 					var sourceMaterial = materials[ mi ]; | ||||||
|  | 					var material = undefined; | ||||||
|  |  | ||||||
|  | 					if ( this.materials !== null ) { | ||||||
|  |  | ||||||
|  | 						material = this.materials.create( sourceMaterial.name ); | ||||||
|  |  | ||||||
|  | 						// mtl etc. loaders probably can't create line materials correctly, copy properties to a line material. | ||||||
|  | 						if ( isLine && material && ! ( material instanceof THREE.LineBasicMaterial ) ) { | ||||||
|  |  | ||||||
|  | 							var materialLine = new THREE.LineBasicMaterial(); | ||||||
|  | 							materialLine.copy( material ); | ||||||
|  | 							material = materialLine; | ||||||
|  |  | ||||||
|  | 						} | ||||||
|  |  | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 					if ( ! material ) { | ||||||
|  |  | ||||||
|  | 						material = ( ! isLine ? new THREE.MeshPhongMaterial() : new THREE.LineBasicMaterial() ); | ||||||
|  | 						material.name = sourceMaterial.name; | ||||||
|  |  | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 					material.flatShading = sourceMaterial.smooth ? false : true; | ||||||
|  |  | ||||||
|  | 					createdMaterials.push( material ); | ||||||
|  |  | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				// Create mesh | ||||||
|  |  | ||||||
|  | 				var mesh; | ||||||
|  |  | ||||||
|  | 				if ( createdMaterials.length > 1 ) { | ||||||
|  |  | ||||||
|  | 					for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { | ||||||
|  |  | ||||||
|  | 						var sourceMaterial = materials[ mi ]; | ||||||
|  | 						buffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi ); | ||||||
|  |  | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 					mesh = ( ! isLine ? new THREE.Mesh( buffergeometry, createdMaterials ) : new THREE.LineSegments( buffergeometry, createdMaterials ) ); | ||||||
|  |  | ||||||
|  | 				} else { | ||||||
|  |  | ||||||
|  | 					mesh = ( ! isLine ? new THREE.Mesh( buffergeometry, createdMaterials[ 0 ] ) : new THREE.LineSegments( buffergeometry, createdMaterials[ 0 ] ) ); | ||||||
|  |  | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				mesh.name = object.name; | ||||||
|  |  | ||||||
|  | 				container.add( mesh ); | ||||||
|  |  | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			console.timeEnd( 'OBJLoader' ); | ||||||
|  |  | ||||||
|  | 			return container; | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	return OBJLoader; | ||||||
|  |  | ||||||
|  | } )(); | ||||||
							
								
								
									
										14
									
								
								static/pkg/solar/js/libs/dat.gui.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										4
									
								
								static/pkg/solar/js/libs/jquery-3.2.1.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										5
									
								
								static/pkg/solar/js/libs/stats.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,5 @@ | |||||||
|  | // stats.js - http://github.com/mrdoob/stats.js | ||||||
|  | var Stats=function(){function h(a){c.appendChild(a.dom);return a}function k(a){for(var d=0;d<c.children.length;d++)c.children[d].style.display=d===a?"none":"none";l=a}var l=0,c=document.createElement("div");c.style.cssText="position:fixed;top:0;left:0;cursor:pointer;opacity:0.9;z-index:10000";c.addEventListener("click",function(a){a.preventDefault();k(++l%c.children.length)},!1);var g=(performance||Date).now(),e=g,a=0,r=h(new Stats.Panel("FPS","#0ff","#002")),f=h(new Stats.Panel("MS","#0f0","#020")); | ||||||
|  | if(self.performance&&self.performance.memory)var t=h(new Stats.Panel("MB","#f08","#201"));k(0);return{REVISION:16,dom:c,addPanel:h,showPanel:k,begin:function(){g=(performance||Date).now()},end:function(){a++;var c=(performance||Date).now();f.update(c-g,200);if(c>e+1E3&&(r.update(1E3*a/(c-e),100),e=c,a=0,t)){var d=performance.memory;t.update(d.usedJSHeapSize/1048576,d.jsHeapSizeLimit/1048576)}return c},update:function(){g=this.end()},domElement:c,setMode:k}}; | ||||||
|  | Stats.Panel=function(h,k,l){var c=Infinity,g=0,e=Math.round,a=e(window.devicePixelRatio||1),r=80*a,f=48*a,t=3*a,u=2*a,d=3*a,m=15*a,n=74*a,p=30*a,q=document.createElement("canvas");q.width=r;q.height=f;q.style.cssText="width:80px;height:48px";var b=q.getContext("2d");b.font="bold "+9*a+"px Helvetica,Arial,sans-serif";b.textBaseline="top";b.fillStyle=l;b.fillRect(0,0,r,f);b.fillStyle=k;b.fillText(h,t,u);b.fillRect(d,m,n,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d,m,n,p);return{dom:q,update:function(f, | ||||||
|  | v){c=Math.min(c,f);g=Math.max(g,f);b.fillStyle=l;b.globalAlpha=1;b.fillRect(0,0,r,m);b.fillStyle=k;b.fillText(e(f)+" "+h+" ("+e(c)+"-"+e(g)+")",t,u);b.drawImage(q,d+a,m,n-a,p,d,m,n-a,p);b.fillRect(d+n-a,m,a,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d+n-a,m,a,e((1-f/v)*p))}}};"object"===typeof module&&(module.exports=Stats); | ||||||
							
								
								
									
										904
									
								
								static/pkg/solar/js/libs/three.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										13
									
								
								static/pkg/solar/js/libs/tween.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,13 @@ | |||||||
|  | // tween.js - http://github.com/sole/tween.js | ||||||
|  | 'use strict';var TWEEN=TWEEN||function(){var a=[];return{REVISION:"7",getAll:function(){return a},removeAll:function(){a=[]},add:function(c){a.push(c)},remove:function(c){c=a.indexOf(c);-1!==c&&a.splice(c,1)},update:function(c){if(0===a.length)return!1;for(var b=0,d=a.length,c=void 0!==c?c:Date.now();b<d;)a[b].update(c)?b++:(a.splice(b,1),d--);return!0}}}(); | ||||||
|  | TWEEN.Tween=function(a){var c={},b={},d=1E3,e=0,f=null,h=TWEEN.Easing.Linear.None,r=TWEEN.Interpolation.Linear,k=[],l=null,m=!1,n=null,p=null;this.to=function(a,c){null!==c&&(d=c);b=a;return this};this.start=function(d){TWEEN.add(this);m=!1;f=void 0!==d?d:Date.now();f+=e;for(var g in b)if(null!==a[g]){if(b[g]instanceof Array){if(0===b[g].length)continue;b[g]=[a[g]].concat(b[g])}c[g]=a[g]}return this};this.stop=function(){TWEEN.remove(this);return this};this.delay=function(a){e=a;return this};this.easing= | ||||||
|  | function(a){h=a;return this};this.interpolation=function(a){r=a;return this};this.chain=function(){k=arguments;return this};this.onStart=function(a){l=a;return this};this.onUpdate=function(a){n=a;return this};this.onComplete=function(a){p=a;return this};this.update=function(e){if(e<f)return!0;!1===m&&(null!==l&&l.call(a),m=!0);var g=(e-f)/d,g=1<g?1:g,i=h(g),j;for(j in c){var s=c[j],q=b[j];a[j]=q instanceof Array?r(q,i):s+(q-s)*i}null!==n&&n.call(a,i);if(1==g){null!==p&&p.call(a);g=0;for(i=k.length;g< | ||||||
|  | i;g++)k[g].start(e);return!1}return!0}}; | ||||||
|  | TWEEN.Easing={Linear:{None:function(a){return a}},Quadratic:{In:function(a){return a*a},Out:function(a){return a*(2-a)},InOut:function(a){return 1>(a*=2)?0.5*a*a:-0.5*(--a*(a-2)-1)}},Cubic:{In:function(a){return a*a*a},Out:function(a){return--a*a*a+1},InOut:function(a){return 1>(a*=2)?0.5*a*a*a:0.5*((a-=2)*a*a+2)}},Quartic:{In:function(a){return a*a*a*a},Out:function(a){return 1- --a*a*a*a},InOut:function(a){return 1>(a*=2)?0.5*a*a*a*a:-0.5*((a-=2)*a*a*a-2)}},Quintic:{In:function(a){return a*a*a* | ||||||
|  | a*a},Out:function(a){return--a*a*a*a*a+1},InOut:function(a){return 1>(a*=2)?0.5*a*a*a*a*a:0.5*((a-=2)*a*a*a*a+2)}},Sinusoidal:{In:function(a){return 1-Math.cos(a*Math.PI/2)},Out:function(a){return Math.sin(a*Math.PI/2)},InOut:function(a){return 0.5*(1-Math.cos(Math.PI*a))}},Exponential:{In:function(a){return 0===a?0:Math.pow(1024,a-1)},Out:function(a){return 1===a?1:1-Math.pow(2,-10*a)},InOut:function(a){return 0===a?0:1===a?1:1>(a*=2)?0.5*Math.pow(1024,a-1):0.5*(-Math.pow(2,-10*(a-1))+2)}},Circular:{In:function(a){return 1- | ||||||
|  | Math.sqrt(1-a*a)},Out:function(a){return Math.sqrt(1- --a*a)},InOut:function(a){return 1>(a*=2)?-0.5*(Math.sqrt(1-a*a)-1):0.5*(Math.sqrt(1-(a-=2)*a)+1)}},Elastic:{In:function(a){var c,b=0.1;if(0===a)return 0;if(1===a)return 1;!b||1>b?(b=1,c=0.1):c=0.4*Math.asin(1/b)/(2*Math.PI);return-(b*Math.pow(2,10*(a-=1))*Math.sin((a-c)*2*Math.PI/0.4))},Out:function(a){var c,b=0.1;if(0===a)return 0;if(1===a)return 1;!b||1>b?(b=1,c=0.1):c=0.4*Math.asin(1/b)/(2*Math.PI);return b*Math.pow(2,-10*a)*Math.sin((a-c)* | ||||||
|  | 2*Math.PI/0.4)+1},InOut:function(a){var c,b=0.1;if(0===a)return 0;if(1===a)return 1;!b||1>b?(b=1,c=0.1):c=0.4*Math.asin(1/b)/(2*Math.PI);return 1>(a*=2)?-0.5*b*Math.pow(2,10*(a-=1))*Math.sin((a-c)*2*Math.PI/0.4):0.5*b*Math.pow(2,-10*(a-=1))*Math.sin((a-c)*2*Math.PI/0.4)+1}},Back:{In:function(a){return a*a*(2.70158*a-1.70158)},Out:function(a){return--a*a*(2.70158*a+1.70158)+1},InOut:function(a){return 1>(a*=2)?0.5*a*a*(3.5949095*a-2.5949095):0.5*((a-=2)*a*(3.5949095*a+2.5949095)+2)}},Bounce:{In:function(a){return 1- | ||||||
|  | TWEEN.Easing.Bounce.Out(1-a)},Out:function(a){return a<1/2.75?7.5625*a*a:a<2/2.75?7.5625*(a-=1.5/2.75)*a+0.75:a<2.5/2.75?7.5625*(a-=2.25/2.75)*a+0.9375:7.5625*(a-=2.625/2.75)*a+0.984375},InOut:function(a){return 0.5>a?0.5*TWEEN.Easing.Bounce.In(2*a):0.5*TWEEN.Easing.Bounce.Out(2*a-1)+0.5}}}; | ||||||
|  | TWEEN.Interpolation={Linear:function(a,c){var b=a.length-1,d=b*c,e=Math.floor(d),f=TWEEN.Interpolation.Utils.Linear;return 0>c?f(a[0],a[1],d):1<c?f(a[b],a[b-1],b-d):f(a[e],a[e+1>b?b:e+1],d-e)},Bezier:function(a,c){var b=0,d=a.length-1,e=Math.pow,f=TWEEN.Interpolation.Utils.Bernstein,h;for(h=0;h<=d;h++)b+=e(1-c,d-h)*e(c,h)*a[h]*f(d,h);return b},CatmullRom:function(a,c){var b=a.length-1,d=b*c,e=Math.floor(d),f=TWEEN.Interpolation.Utils.CatmullRom;return a[0]===a[b]?(0>c&&(e=Math.floor(d=b*(1+c))),f(a[(e- | ||||||
|  | 1+b)%b],a[e],a[(e+1)%b],a[(e+2)%b],d-e)):0>c?a[0]-(f(a[0],a[0],a[1],a[1],-d)-a[0]):1<c?a[b]-(f(a[b],a[b],a[b-1],a[b-1],d-b)-a[b]):f(a[e?e-1:0],a[e],a[b<e+1?b:e+1],a[b<e+2?b:e+2],d-e)},Utils:{Linear:function(a,c,b){return(c-a)*b+a},Bernstein:function(a,c){var b=TWEEN.Interpolation.Utils.Factorial;return b(a)/b(c)/b(a-c)},Factorial:function(){var a=[1];return function(c){var b=1,d;if(a[c])return a[c];for(d=c;1<d;d--)b*=d;return a[c]=b}}(),CatmullRom:function(a,c,b,d,e){var a=0.5*(b-a),d=0.5*(d-c),f= | ||||||
|  | e*e;return(2*c-2*b+a+d)*e*f+(-3*c+3*b-2*a-d)*f+a*e+c}}}; | ||||||
							
								
								
									
										433
									
								
								static/pkg/solar/js/main.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,433 @@ | |||||||
|  | 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() | ||||||
|  | } | ||||||
							
								
								
									
										65
									
								
								static/pkg/solar/js/orbit.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,65 @@ | |||||||
|  | CelestialBody.prototype.updateOrbitAndRotation = function (time) { | ||||||
|  |     // Calculate the orbit | ||||||
|  |     // The reference frame (X, Y, Z) is the center coordinate of | ||||||
|  |     // the object's parent body. | ||||||
|  |     var referenceFrameX = 0; | ||||||
|  |     var referenceFrameY = 0; | ||||||
|  |     var referenceFrameZ = 0; | ||||||
|  |     if (this.parent != null) { | ||||||
|  |         referenceFrameX = this.parent.getX(); | ||||||
|  |         referenceFrameY = this.parent.getY(); | ||||||
|  |         referenceFrameZ = this.parent.getZ(); | ||||||
|  |         // Now this is only a naive way of calculating the orbit | ||||||
|  |         // Note that zOx is the orbit plane | ||||||
|  |         // x -> z   y -> z  z -> x | ||||||
|  |         //1.11version | ||||||
|  |         //r=a*(1-e^2)/(1+ecoswt) | ||||||
|  |         //x=rcoswt+c | ||||||
|  |         //y=rsinwt | ||||||
|  |         var r = this.orbit.semiMajorAxis * (1 - this.orbit.eccentricity * this.orbit.eccentricity) / (1 + this.orbit.eccentricity * Math.cos(10.0 * -time / this.orbit.period)); | ||||||
|  |         var x = referenceFrameX + (r * Math.cos(10.0 * -time / this.orbit.period)) * Math.cos(this.orbit.inclination / 180.0 * Math.PI); | ||||||
|  |         var y = referenceFrameY + (r * Math.cos(10.0 * -time / this.orbit.period)) * Math.sin(this.orbit.inclination / 180.0 * Math.PI); | ||||||
|  |         var z = referenceFrameZ + r * Math.sin(10.0 * -time / this.orbit.period); | ||||||
|  |         if (this.isComet) { | ||||||
|  |             this.cometPivot.position.set(x, y, z); | ||||||
|  |             if (cometSet) { | ||||||
|  |                 this.objectGroup.position.set(x, y, z); | ||||||
|  |                 lastCometX = x; | ||||||
|  |                 lastCometY = y; | ||||||
|  |                 lastCometZ = z; | ||||||
|  |                 cometSet = false; | ||||||
|  |             } | ||||||
|  |             var delta = clock.getDelta() * spawnerOptions.timeScale; | ||||||
|  |             tick += delta; | ||||||
|  |             if (tick < 0) tick = 0; | ||||||
|  |             if (delta > 0) { | ||||||
|  |                 var distance = Math.sqrt(this.getX() * this.getX() + this.getY() * this.getY() + this.getZ() * this.getZ()); | ||||||
|  |                 var tailLength = cometParams["Length"] / distance; | ||||||
|  |                 options.size = cometParams["Size"] / distance; | ||||||
|  |                 this.particleSystem.color = new THREE.Color(); | ||||||
|  |                 options.position.x -= tailLength * x / Math.sqrt(x * x + y * y + z * z); | ||||||
|  |                 options.position.y -= tailLength * y / Math.sqrt(x * x + y * y + z * z); | ||||||
|  |                 options.position.z -= tailLength * z / Math.sqrt(x * x + y * y + z * z); | ||||||
|  |                 // options.sizeRandomness = 2; | ||||||
|  |                 for (var i = 0; i < spawnerOptions.spawnRate * delta; i++) { | ||||||
|  |                     this.particleSystem.spawnParticle(options); | ||||||
|  |                 } | ||||||
|  |                 this.objectGroup.position.x += ( tailLength * x / Math.sqrt(x * x + y * y + z * z) ); | ||||||
|  |                 this.objectGroup.position.y += ( tailLength * y / Math.sqrt(x * x + y * y + z * z) ); | ||||||
|  |                 this.objectGroup.position.z += ( tailLength * z / Math.sqrt(x * x + y * y + z * z) ); | ||||||
|  |                 this.objectGroup.position.x += (x - lastCometX); | ||||||
|  |                 this.objectGroup.position.y += (y - lastCometY); | ||||||
|  |                 this.objectGroup.position.z += (z - lastCometZ); | ||||||
|  |             } | ||||||
|  |             this.particleSystem.update(tick); | ||||||
|  |             lastCometX = x; | ||||||
|  |             lastCometY = y; | ||||||
|  |             lastCometZ = z; | ||||||
|  |         } else { | ||||||
|  |             this.objectGroup.position.set(x, y, z); | ||||||
|  |             // self-rotation | ||||||
|  |             this.objectGroup.rotateOnAxis(new THREE.Vector3(0, 1, 0), 0.1 / this.rotation.period); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     } | ||||||
|  | }; | ||||||
							
								
								
									
										1158
									
								
								static/pkg/solar/js/renderers/CanvasRenderer.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1028
									
								
								static/pkg/solar/js/renderers/Projector.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										129
									
								
								static/pkg/solar/js/shaders.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,129 @@ | |||||||
|  | var generalVS = ` | ||||||
|  | varying vec2 vUv; | ||||||
|  | varying vec3 vNormal; | ||||||
|  |  | ||||||
|  | void main() { | ||||||
|  |     vUv = uv; | ||||||
|  |     vec4 mvPosition = modelViewMatrix * vec4(position, 1.0); | ||||||
|  |     vNormal = normalMatrix * normal; | ||||||
|  |     gl_Position = projectionMatrix * mvPosition; | ||||||
|  | } | ||||||
|  | `; | ||||||
|  |  | ||||||
|  | var nightFS = ` | ||||||
|  | uniform sampler2D nightTexture; | ||||||
|  |  | ||||||
|  | varying vec2 vUv; | ||||||
|  | varying vec3 vNormal; | ||||||
|  |  | ||||||
|  | void main( void ) { | ||||||
|  |     vec4 nightColor = vec4(texture2D( nightTexture, vUv ).rgb, 1.0); | ||||||
|  |     vec4 dayColor = vec4(0, 0, 0, 0); | ||||||
|  |     vec3 sunDirection = vec3(viewMatrix * vec4(0, 0, 0, 1)); | ||||||
|  |  | ||||||
|  |     // compute cosine sun to normal so -1 is away from sun and +1 is toward sun. | ||||||
|  |     float cosineAngleSunToNormal = dot(normalize(vNormal), sunDirection); | ||||||
|  |  | ||||||
|  |     // sharpen the edge beween the transition | ||||||
|  |     cosineAngleSunToNormal = clamp( cosineAngleSunToNormal / 100.0, -1.0, 1.0); | ||||||
|  |  | ||||||
|  |     // convert to 0 to 1 for mixing | ||||||
|  |     float mixAmount = cosineAngleSunToNormal * 0.5 + 0.5; | ||||||
|  |  | ||||||
|  |     // Select day or night texture based on mixAmount. | ||||||
|  |     vec4 color = mix( nightColor, dayColor, mixAmount ); | ||||||
|  |  | ||||||
|  |     gl_FragColor += vec4(color); | ||||||
|  |  | ||||||
|  |     // comment in the next line to see the mixAmount | ||||||
|  |     //gl_FragColor = vec4( mixAmount, mixAmount, mixAmount, 1.0 ); | ||||||
|  | } | ||||||
|  | `; | ||||||
|  |  | ||||||
|  | // This stuff works, currently we do not use the scattering model | ||||||
|  | var atmosphereVS = ` | ||||||
|  |  | ||||||
|  | varying float intensity1; | ||||||
|  | varying float intensity2; | ||||||
|  |  | ||||||
|  | const float PI = 3.14159265358979; | ||||||
|  |  | ||||||
|  | void main(void) { | ||||||
|  |     // Vertex position in world coordinate | ||||||
|  |     vec4 vertexPos = modelMatrix * vec4(position, 1.0); | ||||||
|  |     vec3 vertexPos3 = vertexPos.xyz/vertexPos.w; | ||||||
|  |     // Vertex light position in world coordinate | ||||||
|  |     vec4 lightPos = vec4(0., 0., 0., 1.); | ||||||
|  |     vec3 lightPos3 = lightPos.xyz/lightPos.w; | ||||||
|  |     // Light direction in world coordinate | ||||||
|  |     // Normal vector in world coordinate | ||||||
|  |     // Model view position of the vertex | ||||||
|  |     vec4 modelViewPos = modelViewMatrix * vec4(position, 1.0); | ||||||
|  |     // Camera | ||||||
|  |     vec4 centerPos4 = modelMatrix * vec4(0., 0., 0., 1.); | ||||||
|  |     vec3 centerPos3 = (centerPos4/centerPos4.w).xyz; | ||||||
|  |     vec3 cameraRelative = cameraPosition - centerPos3; | ||||||
|  |  | ||||||
|  |     vec3 cameraDir = normalize(cameraRelative); | ||||||
|  |     vec3 lightDir = normalize(lightPos3 - vertexPos3); | ||||||
|  |     vec3 normalVec = (modelMatrix * vec4(normal, 0.)).xyz; | ||||||
|  |     vec3 halfNormalVec = normalize(normalVec + cameraDir); | ||||||
|  |  | ||||||
|  |     intensity1 = 0.5*dot(lightDir, normalVec + 0.5 * lightDir) * dot(cameraDir + 0.5*lightDir, lightDir) * (1. - pow(dot(cameraDir, normalVec), 1.5)); | ||||||
|  |     intensity2 = 1.5*dot(lightDir, normalVec + lightDir) * (1. - dot(cameraDir + 1.5*lightDir, lightDir)/2.5) * (1. - dot(cameraDir, normalVec)); | ||||||
|  |  | ||||||
|  |     gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); | ||||||
|  | } | ||||||
|  | `; | ||||||
|  |  | ||||||
|  | // Atomosphere fragment shader | ||||||
|  | var atmosphereFS = ` | ||||||
|  | varying float intensity1; | ||||||
|  | varying float intensity2; | ||||||
|  |  | ||||||
|  | uniform vec3 atmosphereColor; | ||||||
|  | uniform vec3 sunsetColor; | ||||||
|  | uniform float atmosphereStrength; | ||||||
|  | uniform float sunsetStrength; | ||||||
|  |  | ||||||
|  | void main(void) { | ||||||
|  |     gl_FragColor = vec4(atmosphereStrength * intensity1 * atmosphereColor | ||||||
|  |         + sunsetStrength * intensity2 * sunsetColor, intensity1 + intensity2); | ||||||
|  | } | ||||||
|  | `; | ||||||
|  |  | ||||||
|  | var haloVS = ` | ||||||
|  | varying float intensity; | ||||||
|  | const float PI = 3.14159265358979; | ||||||
|  |  | ||||||
|  | void main(void) { | ||||||
|  |     // Vertex position in world coordinate | ||||||
|  |     vec4 vertexPos = modelMatrix * vec4(position, 1.0); | ||||||
|  |     vec3 vertexPos3 = vertexPos.xyz/vertexPos.w; | ||||||
|  |     // Light direction in world coordinate | ||||||
|  |     // Normal vector in world coordinate | ||||||
|  |     // Model view position of the vertex | ||||||
|  |     vec4 modelViewPos = modelViewMatrix * vec4(position, 1.0); | ||||||
|  |     float distance = length(cameraPosition); | ||||||
|  |     // Camera | ||||||
|  |     vec4 centerPos4 = modelMatrix * vec4(0., 0., 0., 1.); | ||||||
|  |     vec3 centerPos3 = (centerPos4/centerPos4.w).xyz; | ||||||
|  |     vec3 cameraRelative = cameraPosition - centerPos3; | ||||||
|  |  | ||||||
|  |     vec3 cameraDir = normalize(cameraRelative); | ||||||
|  |     vec3 normalVec = (modelMatrix * vec4(normal, 0.)).xyz; | ||||||
|  | // pow(dot(normalVec, cameraDir), 4.) *  | ||||||
|  |     intensity = pow(dot(normalVec, cameraDir), 4.) * min(distance / 2000., 1.); | ||||||
|  |     gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); | ||||||
|  | } | ||||||
|  | `; | ||||||
|  |  | ||||||
|  | // Atomosphere fragment shader | ||||||
|  | var haloFS = ` | ||||||
|  | varying float intensity; | ||||||
|  | uniform vec3 color; | ||||||
|  |  | ||||||
|  | void main(void) { | ||||||
|  |     gl_FragColor = vec4(intensity * color, intensity); | ||||||
|  | } | ||||||
|  | `; | ||||||
							
								
								
									
										17
									
								
								static/pkg/solar/js/time.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,17 @@ | |||||||
|  | var globalTimeFlag = true; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | var globalTime = { | ||||||
|  |     absolute: 0, | ||||||
|  |     relative: 0, | ||||||
|  |     scale: 1., | ||||||
|  |     getAbsolute: function () { return this.absolute; }, | ||||||
|  |     getRelative: function () { return this.relative; } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | window.setInterval(function () { | ||||||
|  |     if (globalTimeFlag) { | ||||||
|  |         globalTime.relative += 0.001 * globalTime.scale; | ||||||
|  |         globalTime.absolute += 0.001; | ||||||
|  |     } | ||||||
|  | }, 10); | ||||||
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/callisto/diffuse.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 500 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/comet/particle2.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.2 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/comet/perlin-512.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 88 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/deimos/bump.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 26 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/deimos/diffuse.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 49 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/dione/diffuse.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 178 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/earth/bump.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 78 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/earth/clouds.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 897 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/earth/diffuse.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 418 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/earth/night.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.0 MiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/earth/spec.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 170 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/effects/flare.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 13 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/europa/diffuse.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 321 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/io/diffuse.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1014 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/jupiter/clouds.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 974 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/jupiter/diffuse.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 339 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/jupiter/ring.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 652 B | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/loading/earth.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 77 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/loading/splash.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 334 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/mars/bump.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 70 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/mars/diffuse.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 768 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/mercury/bump.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 171 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/mercury/diffuse.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 454 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/moon/bump.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 194 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/moon/diffuse.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 688 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/neptune/diffuse.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 144 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/neptune/ring.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 14 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/phobos/bump.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 23 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/phobos/diffuse.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 82 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/pluto/diffuse.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 393 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/prompt/ding.wav
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/saturn/bump.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 80 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/saturn/clouds.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 129 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/saturn/diffuse.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 197 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/saturn/ring.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.7 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/skybox/negX.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 39 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/skybox/negY.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 29 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/skybox/negZ.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 40 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/skybox/posX.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 47 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/skybox/posY.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 30 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/skybox/posZ.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 108 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/skybox/skydome.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.4 MiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/sol/diffuse.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.7 MiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/sol/overlay.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 169 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/space/lab.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 120 KiB | 
							
								
								
									
										17707
									
								
								static/pkg/solar/res/space/man.obj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/space/sol.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 210 KiB | 
							
								
								
									
										137
									
								
								static/pkg/solar/res/space/tiangong.mtl
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,137 @@ | |||||||
|  | # 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware | ||||||
|  |  | ||||||
|  | newmtl 01___Default | ||||||
|  | 	Ns 50.0000 | ||||||
|  | 	Ni 1.5000 | ||||||
|  | 	d 1.0000 | ||||||
|  | 	Tr 0.0000 | ||||||
|  | 	Tf 1.0000 1.0000 1.0000  | ||||||
|  | 	illum 2 | ||||||
|  | 	Ka 1.0000 1.0000 1.0000 | ||||||
|  | 	Kd 1.0000 1.0000 1.0000 | ||||||
|  | 	Ks 0.0396 0.0396 0.0396 | ||||||
|  | 	Ke 0.0000 0.0000 0.0000 | ||||||
|  | 	map_Ka lab.jpg | ||||||
|  | 	map_Kd lab.jpg | ||||||
|  |  | ||||||
|  | newmtl Material__2 | ||||||
|  | 	Ns 50.0000 | ||||||
|  | 	Ni 1.5000 | ||||||
|  | 	d 1.0000 | ||||||
|  | 	Tr 0.0000 | ||||||
|  | 	Tf 1.0000 1.0000 1.0000  | ||||||
|  | 	illum 2 | ||||||
|  | 	Ka 0.7529 0.7529 0.7529 | ||||||
|  | 	Kd 0.7529 0.7529 0.7529 | ||||||
|  | 	Ks 0.0396 0.0396 0.0396 | ||||||
|  | 	Ke 0.0000 0.0000 0.0000 | ||||||
|  |  | ||||||
|  | newmtl 19___Default | ||||||
|  | 	Ns 50.0000 | ||||||
|  | 	Ni 1.5000 | ||||||
|  | 	d 1.0000 | ||||||
|  | 	Tr 0.0000 | ||||||
|  | 	Tf 1.0000 1.0000 1.0000  | ||||||
|  | 	illum 2 | ||||||
|  | 	Ka 0.7529 0.7529 0.7529 | ||||||
|  | 	Kd 0.7529 0.7529 0.7529 | ||||||
|  | 	Ks 0.0396 0.0396 0.0396 | ||||||
|  | 	Ke 0.0000 0.0000 0.0000 | ||||||
|  |  | ||||||
|  | newmtl 02___Default | ||||||
|  | 	Ns 20.0000 | ||||||
|  | 	Ni 1.5000 | ||||||
|  | 	d 1.0000 | ||||||
|  | 	Tr 0.0000 | ||||||
|  | 	Tf 1.0000 1.0000 1.0000  | ||||||
|  | 	illum 2 | ||||||
|  | 	Ka 0.3098 0.3098 0.3098 | ||||||
|  | 	Kd 0.3098 0.3098 0.3098 | ||||||
|  | 	Ks 0.3169 0.3169 0.3169 | ||||||
|  | 	Ke 0.0000 0.0000 0.0000 | ||||||
|  |  | ||||||
|  | newmtl 07___Default | ||||||
|  | 	Ns 10.0000 | ||||||
|  | 	Ni 1.5000 | ||||||
|  | 	d 1.0000 | ||||||
|  | 	Tr 0.0000 | ||||||
|  | 	Tf 1.0000 1.0000 1.0000  | ||||||
|  | 	illum 2 | ||||||
|  | 	Ka 0.7373 0.7373 0.7373 | ||||||
|  | 	Kd 0.7373 0.7373 0.7373 | ||||||
|  | 	Ks 0.1188 0.1188 0.1188 | ||||||
|  | 	Ke 0.0000 0.0000 0.0000 | ||||||
|  |  | ||||||
|  | newmtl 03___Default | ||||||
|  | 	Ns 30.0000 | ||||||
|  | 	Ni 1.5000 | ||||||
|  | 	d 1.0000 | ||||||
|  | 	Tr 0.0000 | ||||||
|  | 	Tf 1.0000 1.0000 1.0000  | ||||||
|  | 	illum 2 | ||||||
|  | 	Ka 0.3098 0.6000 0.8667 | ||||||
|  | 	Kd 0.3098 0.6000 0.8667 | ||||||
|  | 	Ks 0.7922 0.7922 0.7922 | ||||||
|  | 	Ke 0.0000 0.0000 0.0000 | ||||||
|  |  | ||||||
|  | newmtl 09___Default | ||||||
|  | 	Ns 45.0000 | ||||||
|  | 	Ni 1.5000 | ||||||
|  | 	d 1.0000 | ||||||
|  | 	Tr 0.0000 | ||||||
|  | 	Tf 1.0000 1.0000 1.0000  | ||||||
|  | 	illum 2 | ||||||
|  | 	Ka 0.0000 0.0000 0.0000 | ||||||
|  | 	Kd 0.0000 0.0000 0.0000 | ||||||
|  | 	Ks 0.7129 0.7129 0.7129 | ||||||
|  | 	Ke 0.0000 0.0000 0.0000 | ||||||
|  |  | ||||||
|  | newmtl 08___Default | ||||||
|  | 	Ns 50.0000 | ||||||
|  | 	Ni 1.5000 | ||||||
|  | 	d 1.0000 | ||||||
|  | 	Tr 0.0000 | ||||||
|  | 	Tf 1.0000 1.0000 1.0000  | ||||||
|  | 	illum 2 | ||||||
|  | 	Ka 0.0275 0.0431 0.3294 | ||||||
|  | 	Kd 0.0275 0.0431 0.3294 | ||||||
|  | 	Ks 0.1500 0.1500 0.1500 | ||||||
|  | 	Ke 0.0000 0.0000 0.0000 | ||||||
|  | 	map_Ka sol.jpg | ||||||
|  | 	map_Kd sol.jpg | ||||||
|  |  | ||||||
|  | newmtl 20___Default | ||||||
|  | 	Ns 5.0000 | ||||||
|  | 	Ni 1.5000 | ||||||
|  | 	d 1.0000 | ||||||
|  | 	Tr 0.0000 | ||||||
|  | 	Tf 1.0000 1.0000 1.0000  | ||||||
|  | 	illum 2 | ||||||
|  | 	Ka 0.0039 0.0039 0.0039 | ||||||
|  | 	Kd 0.0039 0.0039 0.0039 | ||||||
|  | 	Ks 0.0792 0.0792 0.0792 | ||||||
|  | 	Ke 0.0000 0.0000 0.0000 | ||||||
|  |  | ||||||
|  | newmtl 14___Default | ||||||
|  | 	Ns 50.0000 | ||||||
|  | 	Ni 1.5000 | ||||||
|  | 	d 1.0000 | ||||||
|  | 	Tr 0.0000 | ||||||
|  | 	Tf 1.0000 1.0000 1.0000  | ||||||
|  | 	illum 2 | ||||||
|  | 	Ka 0.7843 0.7843 0.7843 | ||||||
|  | 	Kd 0.7843 0.7843 0.7843 | ||||||
|  | 	Ks 0.0396 0.0396 0.0396 | ||||||
|  | 	Ke 0.0000 0.0000 0.0000 | ||||||
|  |  | ||||||
|  | newmtl 13___Default | ||||||
|  | 	Ns 81.0000 | ||||||
|  | 	Ni 1.5000 | ||||||
|  | 	d 1.0000 | ||||||
|  | 	Tr 0.0000 | ||||||
|  | 	Tf 1.0000 1.0000 1.0000  | ||||||
|  | 	illum 2 | ||||||
|  | 	Ka 0.5255 0.6588 0.9608 | ||||||
|  | 	Kd 0.5255 0.6588 0.9608 | ||||||
|  | 	Ks 0.5466 0.5466 0.5466 | ||||||
|  | 	Ke 0.0000 0.0000 0.0000 | ||||||
							
								
								
									
										121727
									
								
								static/pkg/solar/res/space/tiangong.obj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/titan/diffuse.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.6 MiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/uranus/diffuse.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 306 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/uranus/ring.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 14 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/venus/bump.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 158 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/venus/clouds.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 79 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/pkg/solar/res/venus/diffuse.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 711 KiB | 
							
								
								
									
										5
									
								
								static/pkg/solar/run.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,5 @@ | |||||||
|  | var connect = require('connect'); | ||||||
|  | var serveStatic = require('serve-static'); | ||||||
|  | connect().use(serveStatic(__dirname)).listen(8080, function(){ | ||||||
|  |     console.log('Server running on 8080...'); | ||||||
|  | }); | ||||||