1
0

add solar

This commit is contained in:
syui 2024-04-28 20:09:32 +09:00
parent 17d3689d50
commit 5958443443
Signed by: syui
GPG Key ID: 5417CFEBAD92DF56
91 changed files with 147231 additions and 2 deletions

View File

@ -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/" 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>
--> -->

View File

@ -12,6 +12,7 @@ function sun_open() {
} }
</script> </script>
<link rel="stylesheet" href="/pkg/particles/particles.css" /> <link rel="stylesheet" href="/pkg/particles/particles.css" />
<div class="sun"> <div class="sun">
<div class="sun-button"> <div class="sun-button">

View File

@ -0,0 +1 @@
<iframe src="/pkg/solar/" allowfullscreen frameborder="0" style="width:100%;height:700px;"></iframe>

View File

@ -22,3 +22,9 @@
- [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
View File

@ -0,0 +1,7 @@
span.story-related-list {
display: none;
}
#story-list{
display:none;
}

View 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;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

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

View 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;
};

View 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;
}

View 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);
}

View 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());
};

View 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
View 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"},
},
}),
}

View 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);

View 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();
};

View 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;

View 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;
}
};

View 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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

5
static/pkg/solar/js/libs/stats.min.js vendored Normal file
View 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

File diff suppressed because one or more lines are too long

13
static/pkg/solar/js/libs/tween.min.js vendored Normal file
View 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
View 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()
}

View 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);
}
}
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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);
}
`;

View 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);

Binary file not shown.

After

Width:  |  Height:  |  Size: 500 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 897 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1014 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 974 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 652 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 768 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 454 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 688 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 393 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

View 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

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 711 KiB

5
static/pkg/solar/run.js Normal file
View 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...');
});