A lot of cleaning, and compilation of the js code
This commit is contained in:
36
js/BouncingCube.js
Normal file
36
js/BouncingCube.js
Normal file
@@ -0,0 +1,36 @@
|
||||
var BouncingCube = function(size, style) {
|
||||
Cube.call(this, size, style);
|
||||
|
||||
this.fixed_center = new THREE.Vector3();
|
||||
this.center = new THREE.Vector3();
|
||||
|
||||
this.speed = new THREE.Vector3(0,0,300);
|
||||
}
|
||||
BouncingCube.prototype = Object.create(Cube.prototype);
|
||||
BouncingCube.prototype.constructor = BouncingCube;
|
||||
|
||||
BouncingCube.prototype.update = function() {
|
||||
// Compute new center
|
||||
var speed_clone = this.speed.clone();
|
||||
speed_clone.multiply(BouncingCube.DT);
|
||||
|
||||
this.speed.add(BouncingCube.G);
|
||||
|
||||
if (this.speed.dot(this.speed) > 100) {
|
||||
this.center.add(speed_clone);
|
||||
}
|
||||
|
||||
if (this.center.z < 0) {
|
||||
this.speed.multiply(BouncingCube.FRICTION);
|
||||
this.center.z = 0;
|
||||
}
|
||||
|
||||
// Update the mesh
|
||||
this.mesh.position.set(this.center.x, this.center.y, this.center.z);
|
||||
}
|
||||
|
||||
// Static variables
|
||||
BouncingCube.DT = new THREE.Vector3(0.1,0.1,0.1);
|
||||
BouncingCube.FRICTION = new THREE.Vector3(1, 1, -0.5);
|
||||
BouncingCube.G = new THREE.Vector3(0,0,-10);
|
||||
|
||||
32
js/BufferGeometryToGeometry.js
Normal file
32
js/BufferGeometryToGeometry.js
Normal file
@@ -0,0 +1,32 @@
|
||||
var Converter = {};
|
||||
|
||||
Converter.toGeometry = function (bg) {
|
||||
// The following snippet is from Mattatz - Masatatsu Nakamura http://mattatz.org
|
||||
var attrib = bg.getAttribute('position');
|
||||
if(attrib === undefined) {
|
||||
throw new Error('a given BufferGeometry object must have a position attribute.');
|
||||
}
|
||||
|
||||
var positions = attrib.array;
|
||||
|
||||
var vertices = [];
|
||||
|
||||
for(var i = 0, n = positions.length; i < n; i += 3) {
|
||||
var x = positions[i];
|
||||
var y = positions[i + 1];
|
||||
var z = positions[i + 2];
|
||||
vertices.push(new THREE.Vector3(x, y, z));
|
||||
}
|
||||
|
||||
var faces = [];
|
||||
|
||||
for(var i = 0, n = vertices.length; i < n; i += 3) {
|
||||
faces.push(new THREE.Face3(i, i + 1, i + 2));
|
||||
}
|
||||
|
||||
var geometry = new THREE.Geometry();
|
||||
geometry.vertices = vertices;
|
||||
geometry.faces = faces;
|
||||
geometry.computeFaceNormals();
|
||||
return geometry;
|
||||
}
|
||||
28
js/Camera.js
Normal file
28
js/Camera.js
Normal file
@@ -0,0 +1,28 @@
|
||||
// class camera extends THREE.PerspectiveCamera
|
||||
var Camera = function() {
|
||||
THREE.PerspectiveCamera.apply(this, arguments);
|
||||
|
||||
this.theta = 0;
|
||||
this.position.x = Camera.DISTANCE_X;
|
||||
this.position.z = Camera.DISTANCE_Z;
|
||||
|
||||
this.up = new THREE.Vector3(0,0,1);
|
||||
this.target = new THREE.Vector3();
|
||||
}
|
||||
Camera.prototype = Object.create(THREE.PerspectiveCamera.prototype);
|
||||
|
||||
// Update function
|
||||
Camera.prototype.update = function() {
|
||||
this.theta += 0.01;
|
||||
this.position.x = Camera.DISTANCE_X*Math.cos(this.theta);
|
||||
this.position.y = Camera.DISTANCE_X*Math.sin(this.theta);
|
||||
}
|
||||
|
||||
// Look function
|
||||
Camera.prototype.look = function() {
|
||||
this.lookAt(this.target);
|
||||
}
|
||||
|
||||
// Static members
|
||||
Camera.DISTANCE_X = 1000;
|
||||
Camera.DISTANCE_Z = 300;
|
||||
77
js/CameraContainer.js
Normal file
77
js/CameraContainer.js
Normal file
@@ -0,0 +1,77 @@
|
||||
var CameraContainer = function (pointerCamera, cameras) {
|
||||
if (cameras !== undefined) {
|
||||
this.cameras = cameras;
|
||||
} else {
|
||||
this.cameras = [];
|
||||
}
|
||||
|
||||
if (pointerCamera !== undefined) {
|
||||
this.push(pointerCamera);
|
||||
}
|
||||
}
|
||||
|
||||
CameraContainer.prototype.mainCamera = function(id) {
|
||||
if (id === undefined) {
|
||||
return this.pointerCamera;
|
||||
}
|
||||
if (id >= cameras.length || id < 0) {
|
||||
console.log('Warning : this camera does not exist');
|
||||
return;
|
||||
}
|
||||
|
||||
this.current_camera = id;
|
||||
}
|
||||
|
||||
CameraContainer.prototype.forEach = function(callback) {
|
||||
callback(this.pointerCamera);
|
||||
this.cameras.forEach(callback);
|
||||
}
|
||||
|
||||
CameraContainer.prototype.look = function() {
|
||||
this.mainCamera().look();
|
||||
}
|
||||
|
||||
CameraContainer.prototype.updateMainCamera = function(time) {
|
||||
this.pointerCamera.update(time);
|
||||
}
|
||||
|
||||
CameraContainer.prototype.update = function(position) {
|
||||
this.cameras.map(function (elt) { elt.update(position); });
|
||||
}
|
||||
|
||||
CameraContainer.prototype.push = function(camera) {
|
||||
this.pointerCamera = camera;
|
||||
this.push = function(camera) {
|
||||
this.cameras.push(camera);
|
||||
};
|
||||
}
|
||||
|
||||
CameraContainer.prototype.get = function(i) {
|
||||
return this.cameras[i];
|
||||
}
|
||||
|
||||
CameraContainer.prototype.getByObject = function(object) {
|
||||
for (var i in this.cameras) {
|
||||
if (this.cameras[i].containsObject(object)) {
|
||||
return this.get(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CameraContainer.prototype.setById = function(id) {
|
||||
var i = this.getById(id);
|
||||
|
||||
if (i !== -1)
|
||||
this.current_camera = i;
|
||||
}
|
||||
|
||||
CameraContainer.prototype.nextCamera = function() {
|
||||
if (this.cameras.length != 0) {
|
||||
this.current_camera++;
|
||||
this.current_camera%=this.cameras.length;
|
||||
}
|
||||
}
|
||||
|
||||
CameraContainer.prototype.map = function(callback) {
|
||||
this.cameras.map(callback);
|
||||
}
|
||||
50
js/Cube.js
Normal file
50
js/Cube.js
Normal file
@@ -0,0 +1,50 @@
|
||||
var Displayable = function() {
|
||||
// Nothing to do here
|
||||
}
|
||||
|
||||
Displayable.prototype.addToScene = function(scene) {
|
||||
scene.add(this.mesh);
|
||||
}
|
||||
|
||||
Displayable.prototype.translate = function(x,y,z) {
|
||||
this.geometry.applyMatrix(new THREE.Matrix4().makeTranslation(x,y,z));
|
||||
}
|
||||
|
||||
// class Cube extends Displayable
|
||||
var Cube = function(size, style) {
|
||||
// Super constructor call
|
||||
Displayable.call(this);
|
||||
|
||||
if (size === undefined) size = 100;
|
||||
if (style === undefined) style = {};
|
||||
|
||||
this.geometry = new THREE.BoxGeometry(size, size, size);
|
||||
// this.geometry.computeVertexNormals();
|
||||
|
||||
this.material = new THREE.MeshLambertMaterial(style);
|
||||
|
||||
this.mesh = new THREE.Mesh(this.geometry, this.material);
|
||||
this.mesh.castShadow = false;
|
||||
}
|
||||
Cube.prototype = Object.create(Displayable.prototype);
|
||||
Cube.prototype.constructor = Cube;
|
||||
|
||||
// class Plane extends Displayable
|
||||
var Plane = function(size1, size2, style) {
|
||||
Displayable.call(this);
|
||||
|
||||
if (style === undefined) style = {};
|
||||
|
||||
this.geometry = new THREE.PlaneBufferGeometry(size1, size2);
|
||||
this.material = new THREE.MeshLambertMaterial(style);
|
||||
this.material.side = THREE.DoubleSide;
|
||||
this.mesh = new THREE.Mesh(this.geometry, this.material);
|
||||
|
||||
this.mesh.receiveShadow = true;
|
||||
}
|
||||
Plane.prototype = Object.create(Displayable.prototype);
|
||||
Plane.prototype.constructor = Plane;
|
||||
|
||||
Plane.prototype.addToScene = function(scene) {
|
||||
scene.add(this.mesh);
|
||||
}
|
||||
201
js/Hermite.js
Normal file
201
js/Hermite.js
Normal file
@@ -0,0 +1,201 @@
|
||||
var Hermite = {};
|
||||
|
||||
Hermite.Polynom = function(t, f, fp) {
|
||||
this.times = t;
|
||||
this.evals = f;
|
||||
this.primes = fp;
|
||||
|
||||
this.baseFunctions = new Array();
|
||||
|
||||
for (var i in this.times) {
|
||||
this.baseFunctions.push(new Hermite.BaseFunction(i, this.times));
|
||||
}
|
||||
|
||||
// Let's do something at least a little reusable
|
||||
this.tools = {};
|
||||
if (f[0] instanceof THREE.Vector3) {
|
||||
this.tools.whatType = 'THREE.Vector3';
|
||||
this.tools.sum = Tools.sum;
|
||||
this.tools.prod = Tools.mul;
|
||||
} else {
|
||||
this.tools.whatType = 'number';
|
||||
this.tools.sum = function(a, b) { return a + b; };
|
||||
this.tools.prod = function(a, b) { return a * b; };
|
||||
}
|
||||
}
|
||||
|
||||
Hermite.Polynom.prototype.eval = function(t) {
|
||||
var ret;
|
||||
|
||||
if (this.tools.whatType === 'THREE.Vector3') {
|
||||
ret = new THREE.Vector3();
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
for (var i in this.times) {
|
||||
var ti = this.times[i];
|
||||
var qi_t = this.baseFunctions[i].eval(t);
|
||||
// var qi_ti = this.baseFunctions[i].eval(ti);
|
||||
|
||||
var qip_ti = this.baseFunctions[i].prime(ti);
|
||||
var f_ti = this.evals[i];
|
||||
var fp_ti = this.primes[i];
|
||||
|
||||
// This is the wikipedia formula
|
||||
// ret += (qi_t / qi_ti) * ((1 - (t - ti) * (qip_ti / qi_ti)) * f_ti + (t - ti) * fp_ti);
|
||||
// Let's not forget that qi_ti = 1
|
||||
|
||||
// This is the final formula
|
||||
// ret += (qi_t) * ((1 - (t - ti) * (qip_ti)) * f_ti + (t - ti) * fp_ti);
|
||||
|
||||
// This is the implementation working with THREE.Vector3
|
||||
// In terms of disgusting code, we're quite good there
|
||||
ret =
|
||||
this.tools.sum(
|
||||
ret,
|
||||
this.tools.prod(
|
||||
this.tools.sum(
|
||||
this.tools.prod(f_ti, 1 - (t - ti) * (qip_ti)),
|
||||
this.tools.prod(fp_ti, t - ti)
|
||||
),
|
||||
qi_t
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Hermite.Polynom.prototype.prime = function(t) {
|
||||
var ret;
|
||||
|
||||
if (this.tools.whatType === 'THREE.Vector3') {
|
||||
ret = new THREE.Vector3();
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
for (var i in this.times) {
|
||||
var ti = this.times[i];
|
||||
var qi_t = this.baseFunctions[i].eval(t);
|
||||
// var qi_ti = this.baseFunctions[i].eval(ti);
|
||||
|
||||
var qip_t = this.baseFunctions[i].prime(t );
|
||||
var qip_ti = this.baseFunctions[i].prime(ti);
|
||||
var f_ti = this.evals[i];
|
||||
var fp_ti = this.primes[i];
|
||||
|
||||
// The return of the disgusting code...
|
||||
// First part is the same that the eval function, but changing qi_t by qip_t
|
||||
// (first part of the derivative)
|
||||
ret =
|
||||
this.tools.sum(
|
||||
ret,
|
||||
this.tools.prod(
|
||||
this.tools.sum(
|
||||
this.tools.prod(f_ti, 1 - (t - ti) * (qip_ti)),
|
||||
this.tools.prod(fp_ti, t - ti)
|
||||
),
|
||||
qip_t
|
||||
)
|
||||
);
|
||||
|
||||
// Here, we just add
|
||||
// ret += qi_t * (-qip_t * f_ti + fp_ti);
|
||||
ret =
|
||||
this.tools.sum(
|
||||
ret,
|
||||
this.tools.prod(
|
||||
this.tools.sum(
|
||||
this.tools.prod(
|
||||
f_ti,
|
||||
-qip_t
|
||||
),
|
||||
fp_ti
|
||||
),
|
||||
qi_t
|
||||
)
|
||||
);
|
||||
|
||||
// Now the following code is the same as the precedent affectation
|
||||
// However it doesn't work, and I can't see the difference between
|
||||
// this and the previous one... so I keep it here, to find the
|
||||
// mistate later
|
||||
// ret =
|
||||
// this.tools.sum(
|
||||
// ret,
|
||||
// this.tools.prod(
|
||||
// this.tools.sum(
|
||||
// fp_ti,
|
||||
// this.tools.prod(
|
||||
// f_ti,
|
||||
// -qip_ti
|
||||
// )
|
||||
// ),
|
||||
// qi_t
|
||||
// )
|
||||
// );
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Hermite.BaseFunction = function(index, times) {
|
||||
this.index = index;
|
||||
this.times = times;
|
||||
}
|
||||
|
||||
Hermite.BaseFunction.prototype.eval = function(t) {
|
||||
var ret = 1;
|
||||
|
||||
for (var i in this.times) {
|
||||
if (i !== this.index) {
|
||||
ret *= (t - this.times[i]) / (this.times[this.index] - this.times[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return ret * ret;
|
||||
}
|
||||
|
||||
Hermite.BaseFunction.prototype.prime = function(t) {
|
||||
var ret = 0;
|
||||
|
||||
for (var i in this.times) {
|
||||
if (i !== this.index) {
|
||||
ret += 2 / (t - this.times[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return this.eval(t) * ret;
|
||||
}
|
||||
|
||||
Hermite.special = {};
|
||||
|
||||
// This polynom interpolates with two coords and one derivative
|
||||
// t = [0,1]
|
||||
Hermite.special.Polynom = function(P0, P1, PP1) {
|
||||
this.tools = {};
|
||||
if (P0 instanceof THREE.Vector3) {
|
||||
this.tools.sum = Tools.sum;
|
||||
this.tools.mul = Tools.mul;
|
||||
this.tools.diff = Tools.diff;
|
||||
this.c = P0.clone();
|
||||
} else {
|
||||
this.tools.sum = function(a,b) { return a+b; };
|
||||
this.tools.mul = function(a,b) { return a*b; };
|
||||
this.tools.diff = function(a,b) { return a-b; };
|
||||
this.c = P0;
|
||||
}
|
||||
|
||||
this.a = this.tools.sum(PP1, this.tools.diff(P0, P1));
|
||||
this.b = this.tools.diff(this.tools.mul(this.tools.diff(P1,P0), 2), PP1);
|
||||
}
|
||||
|
||||
Hermite.special.Polynom.prototype.eval = function(t) {
|
||||
return this.tools.sum(this.tools.mul(this.a, t*t), this.tools.sum(this.tools.mul(this.b, t), this.c));
|
||||
}
|
||||
|
||||
Hermite.special.Polynom.prototype.prime = function(t) {
|
||||
return this.tools.sum(this.tools.mul(this.a,2*t), this.b);
|
||||
}
|
||||
44
js/HermiteTest/HermiteTest.js
Normal file
44
js/HermiteTest/HermiteTest.js
Normal file
@@ -0,0 +1,44 @@
|
||||
var container = document.getElementById('content');
|
||||
|
||||
function print(text) {
|
||||
var content = document.createTextNode(text);
|
||||
var new_line = document.createElement('br');
|
||||
container.appendChild(content);
|
||||
container.appendChild(new_line);
|
||||
}
|
||||
|
||||
function toString(variable) {
|
||||
if (variable instanceof THREE.Vector3) {
|
||||
return variable.x + ', ' + variable.y + ', ' + variable.z;
|
||||
} else {
|
||||
return variable;
|
||||
}
|
||||
}
|
||||
|
||||
// Test with THREE.Vector3
|
||||
// t = [0,1];
|
||||
// f = [new THREE.Vector3(0,0,0), new THREE.Vector3(1,1,1)];
|
||||
// fp = [new THREE.Vector3(0,1,2), new THREE.Vector3(0,0,0)];
|
||||
|
||||
// Test with doubles
|
||||
t = [0,1];
|
||||
f = [0,1];
|
||||
fp = [-1,-1];
|
||||
|
||||
var hermite = new Hermite.special.Polynom(0, 1, -1);
|
||||
|
||||
print('M = [');
|
||||
for (var t = 0; t < 1; t += 0.01) {
|
||||
var res = hermite.eval(t);
|
||||
print("\t" + t + ',' + toString(res) + ';');
|
||||
}
|
||||
print('];');
|
||||
|
||||
print('MP = [');
|
||||
for (var t = 0; t < 1; t += 0.01) {
|
||||
var res = hermite.prime(t);
|
||||
print("\t" + t + ',' + toString(res) + ';');
|
||||
}
|
||||
print('];');
|
||||
|
||||
|
||||
91
js/Logger.js
Normal file
91
js/Logger.js
Normal file
@@ -0,0 +1,91 @@
|
||||
var BD = {};
|
||||
|
||||
BD.Private = {};
|
||||
BD.Private.sendData = function(url, data) {
|
||||
// Append time to data
|
||||
data.time = Date.now() / 1000;
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", url, true);
|
||||
xhr.setRequestHeader("Content-type", "application/json;charset=UTF-8");
|
||||
|
||||
// xhr.onreadystatechange = function() {
|
||||
// if(xhr.readyState == 4 && xhr.status == 200) {
|
||||
// console.log(xhr.responseText);
|
||||
// }
|
||||
// }
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
BD.Private.compactCamera = function(camera) {
|
||||
return {
|
||||
position: {
|
||||
x: camera.position.x,
|
||||
y: camera.position.y,
|
||||
z: camera.position.z
|
||||
},
|
||||
target: {
|
||||
x: camera.target.x,
|
||||
y: camera.target.y,
|
||||
z: camera.target.z
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
BD.Event = {};
|
||||
|
||||
BD.Event.ArrowClicked = function() {};
|
||||
BD.Event.ArrowClicked.prototype.send = function() {
|
||||
var url = "/arrow-clicked";
|
||||
var data = {arrow_id: this.arrow_id};
|
||||
BD.Private.sendData(url, data);
|
||||
}
|
||||
|
||||
BD.Event.CoinClicked = function() {};
|
||||
BD.Event.CoinClicked.prototype.send = function() {
|
||||
var url = "/coin-clicked";
|
||||
var data = {coin_id: this.coin_id};
|
||||
BD.Private.sendData(url, data);
|
||||
}
|
||||
|
||||
BD.Event.KeyboardEvent = function() {};
|
||||
BD.Event.KeyboardEvent.prototype.send = function() {
|
||||
var url = "/keyboard-event";
|
||||
|
||||
var data = {
|
||||
camera: BD.Private.compactCamera(this.camera)
|
||||
}
|
||||
|
||||
BD.Private.sendData(url, data);
|
||||
}
|
||||
|
||||
BD.Event.ResetClicked = function() {};
|
||||
BD.Event.ResetClicked.prototype.send = function() {
|
||||
var url = "/reset-clicked";
|
||||
var data = {};
|
||||
BD.Private.sendData(url, data);
|
||||
}
|
||||
|
||||
BD.Event.PreviousNextClicked = function() {};
|
||||
BD.Event.PreviousNextClicked.prototype.send = function() {
|
||||
var url = "/previous-next-clicked";
|
||||
var data = {
|
||||
// casts previous to boolean
|
||||
previous: this.previous,
|
||||
camera: BD.Private.compactCamera(this.camera)
|
||||
};
|
||||
|
||||
BD.Private.sendData(url, data);
|
||||
}
|
||||
|
||||
BD.Event.Hovered = function() {};
|
||||
BD.Event.Hovered.prototype.send = function() {
|
||||
var url = "/hovered";
|
||||
var data = {
|
||||
start: this.start,
|
||||
arrow_id: this.arrow_id
|
||||
};
|
||||
|
||||
BD.Private.sendData(url, data);
|
||||
}
|
||||
78
js/Makefile
Normal file
78
js/Makefile
Normal file
@@ -0,0 +1,78 @@
|
||||
OPT=--compilation_level SIMPLE_OPTIMIZATIONS
|
||||
CLOSURE=java -jar /usr/share/java/closure-compiler/closure-compiler.jar
|
||||
|
||||
all: Three Stats ThreeTools Bouncing Multisphere StreamingSimulator PrototypeTools PrototypeReplay PrototypeInteractive
|
||||
|
||||
Three:
|
||||
cp three/three.min.js ../static/js/
|
||||
|
||||
Stats:
|
||||
cp three/stats.min.js ../static/js/
|
||||
|
||||
ThreeTools:
|
||||
$(CLOSURE) $(OPT) \
|
||||
--js three/DDSLoader.js \
|
||||
--js three/MTLLoader.js \
|
||||
--js three/OBJMTLLoader.js \
|
||||
--js three/OBJLoader.js \
|
||||
--js three/OrbitControls.js \
|
||||
--js Tools.js \
|
||||
--js_output_file ../static/js/threetools.min.js
|
||||
|
||||
Bouncing:
|
||||
$(CLOSURE) $(OPT) \
|
||||
--js Camera.js \
|
||||
--js Cube.js \
|
||||
--js BouncingCube.js \
|
||||
--js bouncing/BouncingMain.js \
|
||||
--js_output_file ../static/js/bouncing.min.js
|
||||
|
||||
Multisphere:
|
||||
$(CLOSURE) $(OPT) \
|
||||
--js StaticPath.js \
|
||||
--js Camera.js \
|
||||
--js Cube.js \
|
||||
--js multisphere/MultiSphere.js \
|
||||
--js_output_file ../static/js/multisphere.min.js
|
||||
|
||||
StreamingSimulator:
|
||||
$(CLOSURE) $(OPT) \
|
||||
--js StaticPath.js \
|
||||
--js Camera.js \
|
||||
--js Cube.js \
|
||||
--js ProgressiveSphere.js \
|
||||
--js stream/main.js \
|
||||
--js_output_file ../static/js/streamingsimulator.min.js
|
||||
|
||||
PrototypeTools:
|
||||
$(CLOSURE) $(OPT) \
|
||||
--js StaticPath.js \
|
||||
--js Hermite.js \
|
||||
--js Camera.js \
|
||||
--js PointerCamera.js \
|
||||
--js CameraContainer.js \
|
||||
--js prototype/ArrowCamera.js \
|
||||
--js prototype/FixedCamera.js \
|
||||
--js prototype/OldFixedCamera.js \
|
||||
--js prototype/ReverseCamera.js \
|
||||
--js prototype/ReplayCamera.js \
|
||||
--js prototype/initScene.js \
|
||||
--js prototype/raycasterTools.js \
|
||||
--js prototype/Previewer.js \
|
||||
--js prototype/ButtonManager.js \
|
||||
--js prototype/Coin.js \
|
||||
--js Logger.js \
|
||||
--js_output_file ../static/js/prototypetools.min.js
|
||||
|
||||
PrototypeInteractive:
|
||||
$(CLOSURE) $(OPT) \
|
||||
--js prototype/main.js \
|
||||
--js_output_file ../static/js/prototypeinteractive.min.js
|
||||
|
||||
PrototypeReplay:
|
||||
$(CLOSURE) $(OPT) \
|
||||
--js prototype/replay.js \
|
||||
--js_output_file ../static/js/replay.min.js
|
||||
|
||||
clean:
|
||||
rm -ri ../static/js/*
|
||||
422
js/PointerCamera.js
Normal file
422
js/PointerCamera.js
Normal file
@@ -0,0 +1,422 @@
|
||||
// class camera extends THREE.PerspectiveCamera
|
||||
var PointerCamera = function() {
|
||||
THREE.PerspectiveCamera.apply(this, arguments);
|
||||
|
||||
if (arguments[4] === undefined)
|
||||
listenerTarget = document;
|
||||
else
|
||||
listenerTarget = arguments[4];
|
||||
|
||||
// Set Position
|
||||
this.theta = Math.PI;
|
||||
this.phi = Math.PI;
|
||||
|
||||
// this.keyboard = undefined;
|
||||
this.moving = false;
|
||||
|
||||
this.dragging = false;
|
||||
this.mouse = {x: 0, y: 0};
|
||||
this.mouseMove = {x: 0, y: 0};
|
||||
|
||||
|
||||
// Stuff for rendering
|
||||
this.position = new THREE.Vector3();
|
||||
this.forward = new THREE.Vector3();
|
||||
this.left = new THREE.Vector3();
|
||||
this.target = new THREE.Vector3(0,1,0);
|
||||
|
||||
// Stuff for events
|
||||
this.motion = {};
|
||||
|
||||
this.sensitivity = 0.05;
|
||||
this.speed = 1;
|
||||
|
||||
// Raycaster for collisions
|
||||
this.raycaster = new THREE.Raycaster();
|
||||
|
||||
// Create history object
|
||||
this.history = new History();
|
||||
|
||||
// Set events from the document
|
||||
var self = this;
|
||||
var onKeyDown = function(event) {self.onKeyDown(event);};
|
||||
var onKeyUp = function(event) {self.onKeyUp(event);};
|
||||
var onMouseDown = function(event) {self.onMouseDown(event); };
|
||||
var onMouseMove = function(event) {self.onMouseMove(event); };
|
||||
var onMouseUp = function(event) {self.onMouseUp(event); };
|
||||
|
||||
document.addEventListener('keydown', onKeyDown, false);
|
||||
document.addEventListener('keyup', onKeyUp, false);
|
||||
listenerTarget.addEventListener('mousedown', function(event) { if (event.which == 1) onMouseDown(event);}, false);
|
||||
listenerTarget.addEventListener('mousemove', function(event) { if (event.which == 1) onMouseMove(event);}, false);
|
||||
listenerTarget.addEventListener('mouseup', onMouseUp, false);
|
||||
// listenerTarget.addEventListener('mouseup', function() { console.log("mouseup");}, false);
|
||||
// listenerTarget.addEventListener('mouseout', onMouseUp, false);
|
||||
|
||||
this.collisions = true;
|
||||
}
|
||||
PointerCamera.prototype = Object.create(THREE.PerspectiveCamera.prototype);
|
||||
PointerCamera.prototype.constructor = PointerCamera;
|
||||
|
||||
// Update function
|
||||
PointerCamera.prototype.update = function(time) {
|
||||
if (this.moving) {
|
||||
this.linearMotion(time);
|
||||
} else if (this.movingHermite) {
|
||||
this.hermiteMotion(time);
|
||||
} else {
|
||||
this.normalMotion(time);
|
||||
}
|
||||
}
|
||||
|
||||
PointerCamera.prototype.linearMotion = function(time) {
|
||||
var position_direction = Tools.diff(this.new_position, this.position);
|
||||
var target_direction = Tools.diff(this.new_target, this.target);
|
||||
|
||||
this.position.add(Tools.mul(position_direction, 0.05 * time / 20));
|
||||
this.target.add(Tools.mul(target_direction, 0.05 * time / 20));
|
||||
|
||||
if (Tools.norm2(Tools.diff(this.position, this.new_position)) < 0.01 &&
|
||||
Tools.norm2(Tools.diff(this.target, this.new_target)) < 0.01) {
|
||||
this.moving = false;
|
||||
this.anglesFromVectors();
|
||||
}
|
||||
}
|
||||
|
||||
PointerCamera.prototype.hermiteMotion = function(time) {
|
||||
var eval = this.hermitePosition.eval(this.t);
|
||||
this.position.x = eval.x;
|
||||
this.position.y = eval.y;
|
||||
this.position.z = eval.z;
|
||||
|
||||
this.target = Tools.sum(this.position, this.hermiteAngles.eval(this.t));
|
||||
|
||||
this.t += 0.01 * time / 20;
|
||||
|
||||
if (this.t > 1) {
|
||||
this.movingHermite = false;
|
||||
this.anglesFromVectors();
|
||||
}
|
||||
}
|
||||
|
||||
PointerCamera.prototype.normalMotion = function(time) {
|
||||
// Update angles
|
||||
if (this.motion.increasePhi) {this.phi += this.sensitivity; this.changed = true; }
|
||||
if (this.motion.decreasePhi) {this.phi -= this.sensitivity; this.changed = true; }
|
||||
if (this.motion.increaseTheta) {this.theta += this.sensitivity; this.changed = true; }
|
||||
if (this.motion.decreaseTheta) {this.theta -= this.sensitivity; this.changed = true; }
|
||||
|
||||
if (this.dragging) {
|
||||
this.theta += this.mouseMove.x;
|
||||
this.phi -= this.mouseMove.y;
|
||||
|
||||
this.mouseMove.x = 0;
|
||||
this.mouseMove.y = 0;
|
||||
|
||||
this.changed = true;
|
||||
}
|
||||
|
||||
// Clamp phi and theta
|
||||
this.phi = Math.min(Math.max(-(Math.PI/2-0.1),this.phi), Math.PI/2-0.1);
|
||||
this.theta = ((this.theta - Math.PI) % (2*Math.PI)) + Math.PI;
|
||||
|
||||
// Compute vectors (position and target)
|
||||
this.vectorsFromAngles();
|
||||
|
||||
// Update with events
|
||||
var delta = 0.1;
|
||||
var forward = this.forward.clone();
|
||||
forward.multiplyScalar(400.0 * delta);
|
||||
var left = this.up.clone();
|
||||
left.cross(forward);
|
||||
left.normalize();
|
||||
left.multiplyScalar(400.0 * delta);
|
||||
|
||||
// Move only if no collisions
|
||||
var speed = this.speed * time / 20;
|
||||
var direction = new THREE.Vector3();
|
||||
|
||||
if (this.motion.boost) speed *= 10;
|
||||
if (this.motion.moveForward) {direction.add(Tools.mul(forward, speed)); this.changed = true;}
|
||||
if (this.motion.moveBackward) {direction.sub(Tools.mul(forward, speed)); this.changed = true;}
|
||||
if (this.motion.moveLeft) {direction.add(Tools.mul(left, speed)); this.changed = true;}
|
||||
if (this.motion.moveRight) {direction.sub(Tools.mul(left, speed)); this.changed = true;}
|
||||
|
||||
if (!this.collisions || !this.isColliding(direction)) {
|
||||
this.position.add(direction);
|
||||
}
|
||||
|
||||
// Update angle
|
||||
this.target = this.position.clone();
|
||||
this.target.add(forward);
|
||||
}
|
||||
|
||||
PointerCamera.prototype.reset = function() {
|
||||
this.resetBobomb();
|
||||
this.moving = false;
|
||||
this.movingHermite = false;
|
||||
(new BD.Event.ResetClicked()).send();
|
||||
// this.position.copy(new THREE.Vector3(-8.849933489419644, 9.050627639459208, 0.6192960680432451));
|
||||
// this.target.copy(new THREE.Vector3(17.945323228767702, -15.156828589982375, -16.585740412769756));
|
||||
// this.anglesFromVectors();
|
||||
}
|
||||
|
||||
PointerCamera.prototype.resetBobomb = function() {
|
||||
this.position.copy(new THREE.Vector3(34.51854618261728,10.038879540840306,-21.772598201888613));
|
||||
this.target.copy(new THREE.Vector3(-2.593404107644737,8.039712770013185,-6.983870133675925));
|
||||
this.anglesFromVectors();
|
||||
}
|
||||
|
||||
PointerCamera.prototype.vectorsFromAngles = function() {
|
||||
// Update direction
|
||||
this.forward.y = Math.sin(this.phi);
|
||||
|
||||
var cos = Math.cos(this.phi);
|
||||
this.forward.z = cos * Math.cos(this.theta);
|
||||
this.forward.x = cos * Math.sin(this.theta);
|
||||
this.forward.normalize();
|
||||
|
||||
}
|
||||
|
||||
PointerCamera.prototype.anglesFromVectors = function() {
|
||||
var forward = Tools.diff(this.target, this.position);
|
||||
forward.normalize();
|
||||
|
||||
this.phi = Math.asin(forward.y);
|
||||
|
||||
// Don't know why this line works... But thanks Thierry-san and
|
||||
// Bastien because it seems to work...
|
||||
this.theta = Math.atan2(forward.x, forward.z);
|
||||
}
|
||||
|
||||
PointerCamera.prototype.move = function(otherCamera, toSave) {
|
||||
if (toSave === undefined)
|
||||
toSave = true;
|
||||
|
||||
this.moving = true;
|
||||
this.new_target = otherCamera.target.clone();
|
||||
this.new_position = otherCamera.position.clone();
|
||||
var t = [0,1];
|
||||
var f = [this.position.clone(), this.new_position];
|
||||
var fp = [Tools.diff(this.target, this.position), Tools.diff(this.new_target, this.new_position)];
|
||||
this.hermite = new Hermite.Polynom(t,f,fp);
|
||||
this.t = 0;
|
||||
|
||||
if (toSave) {
|
||||
if (this.changed) {
|
||||
this.save();
|
||||
this.changed = false;
|
||||
}
|
||||
this.history.addState({position: otherCamera.position.clone(), target: otherCamera.target.clone()});
|
||||
}
|
||||
}
|
||||
|
||||
PointerCamera.prototype.moveHermite = function(otherCamera, toSave) {
|
||||
if (toSave === undefined)
|
||||
toSave = true;
|
||||
|
||||
this.movingHermite = true;
|
||||
this.t = 0;
|
||||
|
||||
this.hermitePosition = new Hermite.special.Polynom(
|
||||
this.position.clone(),
|
||||
otherCamera.position.clone(),
|
||||
Tools.mul(Tools.diff(otherCamera.target, otherCamera.position).normalize(),4)
|
||||
);
|
||||
|
||||
this.hermiteAngles = new Hermite.special.Polynom(
|
||||
Tools.diff(this.target, this.position),
|
||||
Tools.diff(otherCamera.target, otherCamera.position),
|
||||
new THREE.Vector3()
|
||||
);
|
||||
|
||||
if (toSave) {
|
||||
if (this.changed) {
|
||||
this.save();
|
||||
this.changed = false;
|
||||
}
|
||||
this.history.addState({position: otherCamera.position.clone(), target: otherCamera.target.clone()});
|
||||
}
|
||||
}
|
||||
|
||||
PointerCamera.prototype.isColliding = function(direction) {
|
||||
this.raycaster.set(this.position, direction.clone().normalize());
|
||||
var intersects = this.raycaster.intersectObjects(this.collidableObjects, true);
|
||||
|
||||
for (var i in intersects) {
|
||||
if (intersects[i].distance < 100*this.speed) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Look function
|
||||
PointerCamera.prototype.look = function() {
|
||||
this.lookAt(this.target);
|
||||
}
|
||||
|
||||
PointerCamera.prototype.addToScene = function(scene) {
|
||||
scene.add(this);
|
||||
}
|
||||
|
||||
PointerCamera.prototype.onKeyEvent = function(event, toSet) {
|
||||
// Create copy of state
|
||||
var motionJsonCopy = JSON.stringify(this.motion);
|
||||
|
||||
switch ( event.keyCode ) {
|
||||
// Azerty keyboards
|
||||
case 38: case 90: this.motion.moveForward = toSet; break; // up / z
|
||||
case 37: case 81: this.motion.moveLeft = toSet; break; // left / q
|
||||
case 40: case 83: this.motion.moveBackward = toSet; break; // down / s
|
||||
case 39: case 68: this.motion.moveRight = toSet; break; // right / d
|
||||
case 32: this.motion.boost = toSet; break;
|
||||
|
||||
// Qwerty keyboards
|
||||
case 38: case 87: this.motion.moveForward = toSet; break; // up / w
|
||||
case 37: case 65: this.motion.moveLeft = toSet; break; // left / a
|
||||
case 40: case 83: this.motion.moveBackward = toSet; break; // down / s
|
||||
case 39: case 68: this.motion.moveRight = toSet; break; // right / d
|
||||
|
||||
case 73: case 104: this.motion.increasePhi = toSet; break; // 8 Up for angle
|
||||
case 75: case 98: this.motion.decreasePhi = toSet; break; // 2 Down for angle
|
||||
case 74: case 100: this.motion.increaseTheta = toSet; break; // 4 Left for angle
|
||||
case 76: case 102: this.motion.decreaseTheta = toSet; break; // 6 Right for angle
|
||||
|
||||
case 13: if (toSet) this.log(); break;
|
||||
}
|
||||
if (motionJsonCopy != JSON.stringify(this.motion)) {
|
||||
// Log any change
|
||||
var event = new BD.Event.KeyboardEvent();
|
||||
event.camera = this;
|
||||
event.send();
|
||||
}
|
||||
}
|
||||
|
||||
PointerCamera.prototype.onKeyDown = function(event) {
|
||||
this.onKeyEvent(event, true);
|
||||
}
|
||||
|
||||
PointerCamera.prototype.onKeyUp = function(event) {
|
||||
this.onKeyEvent(event, false);
|
||||
}
|
||||
|
||||
PointerCamera.prototype.onMouseDown = function(event) {
|
||||
this.mouse.x = ( ( event.clientX - renderer.domElement.offsetLeft ) / renderer.domElement.width ) * 2 - 1;
|
||||
this.mouse.y = - ( ( event.clientY - renderer.domElement.offsetTop ) / renderer.domElement.height ) * 2 + 1;
|
||||
|
||||
this.dragging = true;
|
||||
this.mouseMoved = false;
|
||||
}
|
||||
|
||||
PointerCamera.prototype.onMouseMove = function(event) {
|
||||
if (this.dragging) {
|
||||
var mouse = {x: this.mouse.x, y: this.mouse.y};
|
||||
this.mouse.x = ( ( event.clientX - renderer.domElement.offsetLeft ) / renderer.domElement.width ) * 2 - 1;
|
||||
this.mouse.y = - ( ( event.clientY - renderer.domElement.offsetTop ) / renderer.domElement.height ) * 2 + 1;
|
||||
|
||||
this.mouseMove.x = this.mouse.x - mouse.x;
|
||||
this.mouseMove.y = this.mouse.y - mouse.y;
|
||||
this.mouseMoved = true;
|
||||
}
|
||||
}
|
||||
|
||||
PointerCamera.prototype.onMouseUp = function(event) {
|
||||
this.onMouseMove(event);
|
||||
|
||||
// Send log to DB
|
||||
if (this.dragging && this.mouseMoved && !this.moving && !this.movingHermite) {
|
||||
var event = new BD.Event.KeyboardEvent();
|
||||
event.camera = this;
|
||||
event.send();
|
||||
}
|
||||
|
||||
this.dragging = false;
|
||||
}
|
||||
|
||||
PointerCamera.prototype.log = function() {
|
||||
console.log("createCamera(\nnew THREE.Vector3(" + this.position.x + "," + this.position.y + ',' + this.position.z + '),\n'
|
||||
+ "new THREE.Vector3(" + this.target.x + "," + this.target.y + ',' + this.target.z + ')\n)');
|
||||
}
|
||||
|
||||
PointerCamera.prototype.save = function() {
|
||||
var backup = {};
|
||||
backup.position = this.position.clone();
|
||||
backup.target = this.target.clone();
|
||||
this.history.addState(backup);
|
||||
}
|
||||
|
||||
PointerCamera.prototype.undo = function() {
|
||||
var move = this.history.undo();
|
||||
if (move !== undefined) {
|
||||
var event = new BD.Event.PreviousNextClicked();
|
||||
event.previous = true;
|
||||
event.camera = move;
|
||||
event.send();
|
||||
|
||||
this.move(move, false);
|
||||
}
|
||||
}
|
||||
|
||||
PointerCamera.prototype.redo = function() {
|
||||
var move = this.history.redo();
|
||||
if (move !== undefined) {
|
||||
var event = new BD.Event.PreviousNextClicked();
|
||||
event.previous = false;
|
||||
event.camera = move;
|
||||
event.send();
|
||||
|
||||
this.move(move, false);
|
||||
}
|
||||
}
|
||||
|
||||
PointerCamera.prototype.undoable = function() {
|
||||
return this.history.undoable();
|
||||
}
|
||||
|
||||
PointerCamera.prototype.redoable = function() {
|
||||
return this.history.redoable();
|
||||
}
|
||||
|
||||
var History = function() {
|
||||
this.states = new Array();
|
||||
this.index = -1;
|
||||
this.size = 0;
|
||||
console.log('New state ' + this.index + ' / ' + this.size);
|
||||
}
|
||||
|
||||
History.prototype.addState = function(state) {
|
||||
++this.index;
|
||||
this.size = this.index + 1;
|
||||
this.states[this.size-1] = state;
|
||||
console.log('New state ' + this.index + ' / ' + this.size);
|
||||
}
|
||||
|
||||
History.prototype.undo = function() {
|
||||
if (this.undoable()) {
|
||||
this.index--;
|
||||
console.log('New state ' + this.index + ' / ' + this.size);
|
||||
return this.currentState();
|
||||
}
|
||||
}
|
||||
|
||||
History.prototype.redo = function() {
|
||||
if (this.redoable()) {
|
||||
this.index++;
|
||||
console.log('New state ' + this.index + ' / ' + this.size);
|
||||
return this.currentState();
|
||||
}
|
||||
}
|
||||
|
||||
History.prototype.undoable = function() {
|
||||
return this.index > 0;
|
||||
}
|
||||
|
||||
History.prototype.redoable = function() {
|
||||
return this.index < this.size - 1;
|
||||
}
|
||||
|
||||
History.prototype.currentState = function() {
|
||||
return this.states[this.index];
|
||||
}
|
||||
89
js/ProgressiveSphere.js
Normal file
89
js/ProgressiveSphere.js
Normal file
@@ -0,0 +1,89 @@
|
||||
var ProgessiveSphere = function(loader, res) {
|
||||
Displayable.call(this);
|
||||
this.started = false;
|
||||
this.finished = false;
|
||||
this.wasFinished = false;
|
||||
this.begin = false;
|
||||
this.addedToScene = false;
|
||||
|
||||
if (res === undefined)
|
||||
res = 5;
|
||||
|
||||
(function(self) {
|
||||
loader.load(static_path + 'data/spheres/' + res + '.obj', function(object) {
|
||||
object.traverse(function(child) {
|
||||
if (child instanceof THREE.Mesh) {
|
||||
child.up = new THREE.Vector3(0,0,1);
|
||||
self.totalMesh = child;
|
||||
self.geometry = new THREE.Geometry();
|
||||
self.material = new THREE.MeshLambertMaterial();
|
||||
self.material.color.setRGB(1,0,0);
|
||||
self.material.side = THREE.DoubleSide;
|
||||
self.mesh = new THREE.Mesh(self.geometry, self.material);
|
||||
self.current_face = 0;
|
||||
self.started = true;
|
||||
self.begin = true;
|
||||
self.addToScene(scene);
|
||||
}
|
||||
});
|
||||
});
|
||||
})(this);
|
||||
|
||||
}
|
||||
ProgessiveSphere.prototype = Object.create(Displayable.prototype);
|
||||
ProgessiveSphere.prototype.constructor = ProgessiveSphere;
|
||||
|
||||
ProgessiveSphere.prototype.addFace = function() {
|
||||
if (this.started && this.begin && this.addedToScene) {
|
||||
if (this.current_face < this.totalMesh.geometry.attributes.position.array.length / 3) {
|
||||
|
||||
// Add the 3 new vertices
|
||||
this.geometry.vertices.push(new THREE.Vector3(
|
||||
this.totalMesh.geometry.attributes.position.array[3*this.current_face],
|
||||
this.totalMesh.geometry.attributes.position.array[3*this.current_face+1],
|
||||
this.totalMesh.geometry.attributes.position.array[3*this.current_face+2]
|
||||
));
|
||||
|
||||
this.geometry.vertices.push(new THREE.Vector3(
|
||||
this.totalMesh.geometry.attributes.position.array[3*this.current_face+3],
|
||||
this.totalMesh.geometry.attributes.position.array[3*this.current_face+4],
|
||||
this.totalMesh.geometry.attributes.position.array[3*this.current_face+5]
|
||||
));
|
||||
|
||||
this.geometry.vertices.push(new THREE.Vector3(
|
||||
this.totalMesh.geometry.attributes.position.array[3*this.current_face+6],
|
||||
this.totalMesh.geometry.attributes.position.array[3*this.current_face+7],
|
||||
this.totalMesh.geometry.attributes.position.array[3*this.current_face+8]
|
||||
));
|
||||
|
||||
// Add the new face
|
||||
this.geometry.faces.push(new THREE.Face3(
|
||||
this.geometry.vertices.length-3,
|
||||
this.geometry.vertices.length-2,
|
||||
this.geometry.vertices.length-1
|
||||
));
|
||||
|
||||
// Update the stuff
|
||||
this.geometry.mergeVertices();
|
||||
this.geometry.computeFaceNormals();
|
||||
this.geometry.computeVertexNormals();
|
||||
this.current_face += 3;
|
||||
this.geometry.elementsNeedUpdate = true;
|
||||
this.geometry.normalsNeedUpdate = true;
|
||||
this.geometry.verticesNeedUpdate = true;
|
||||
this.geometry.groupsNeedUpdate = true;
|
||||
} else {
|
||||
this.finished = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.wasFinished && this.finished) {
|
||||
this.wasFinished = true;
|
||||
console.log("Finished reconstructing the mesh !");
|
||||
}
|
||||
}
|
||||
|
||||
ProgessiveSphere.prototype.addToScene = function(scene) {
|
||||
Displayable.prototype.addToScene.call(this, scene);
|
||||
this.addedToScene = true;
|
||||
}
|
||||
1
js/StaticPath.js
Normal file
1
js/StaticPath.js
Normal file
@@ -0,0 +1 @@
|
||||
static_path = "/static/";
|
||||
37
js/Tools.js
Normal file
37
js/Tools.js
Normal file
@@ -0,0 +1,37 @@
|
||||
var Tools = {version : "1.0" };
|
||||
|
||||
Tools.sum = function(v1, v2) {
|
||||
return new THREE.Vector3(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
|
||||
}
|
||||
|
||||
Tools.diff = function(v1, v2) {
|
||||
return new THREE.Vector3(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
|
||||
}
|
||||
|
||||
Tools.dot = function(v1, v2) {
|
||||
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
|
||||
}
|
||||
|
||||
Tools.cross = function(v1, v2) {
|
||||
return new THREE.Vector3(
|
||||
v1.y * v2.z - v1.z * v2.y,
|
||||
v1.z * v2.x - v1.x * v2.z,
|
||||
v1.x * v2.y - v1.y * v2.x
|
||||
);
|
||||
}
|
||||
|
||||
Tools.mul = function(v1, lambda) {
|
||||
return new THREE.Vector3(v1.x * lambda, v1.y * lambda, v1.z * lambda);
|
||||
}
|
||||
|
||||
Tools.equals = function(v1, v2) {
|
||||
return v1.x == v2.x && v1.y == v2.y && v1.z == v2.z;
|
||||
}
|
||||
|
||||
Tools.norm2 = function(v) {
|
||||
return v.x * v.x + v.y * v.y + v.z * v.z;
|
||||
}
|
||||
|
||||
Tools.norm = function(v) {
|
||||
return Math.sqrt(Tools.norm2(v));
|
||||
}
|
||||
79
js/ToolsTest.js
Normal file
79
js/ToolsTest.js
Normal file
@@ -0,0 +1,79 @@
|
||||
function test(b) {
|
||||
if (b)
|
||||
document.write("<li style='color: #008800'>Success !</li>");
|
||||
else
|
||||
document.write("<li style='color: red'>Failure !</li>");
|
||||
}
|
||||
|
||||
function main() {
|
||||
document.write("<h1>Starting test !</h1>");
|
||||
|
||||
var v1 = new THREE.Vector3(1,2,3);
|
||||
var v2 = new THREE.Vector3(2,3,4);
|
||||
var v1Bak = v1.clone();
|
||||
var v2Bak = v2.clone();
|
||||
|
||||
// First tests
|
||||
document.write("<ol>");
|
||||
var v3 = Tools.sum(v1,v2);
|
||||
test(v3.x == v1.x + v2.x && v3.y == v1.y + v2.y && v3.z == v1.z + v2.z);
|
||||
test(Tools.equals(v1, v1Bak));
|
||||
test(Tools.equals(v2, v2Bak));
|
||||
document.write('</ol>');
|
||||
|
||||
// Clear v1, v2
|
||||
v1 = v1Bak.clone();
|
||||
v2 = v2Bak.clone();
|
||||
|
||||
document.write("<ol>");
|
||||
var v4 = Tools.diff(v1,v2);
|
||||
test(v4.x == v1.x - v2.x && v4.y == v1.y - v2.y && v4.z == v1.z - v2.z);
|
||||
test(Tools.equals(v1, v1Bak));
|
||||
test(Tools.equals(v2, v2Bak));
|
||||
document.write('</ol>');
|
||||
|
||||
v1 = v1Bak.clone();
|
||||
v2 = v2Bak.clone();
|
||||
|
||||
document.write("<ol>");
|
||||
var v5 = Tools.dot(v1,v2);
|
||||
test(v5 == v1.x * v2.x + v1.y * v2.y + v1.z * v2.z);
|
||||
test(Tools.equals(v1, v1Bak));
|
||||
test(Tools.equals(v2, v2Bak));
|
||||
document.write('</ol>');
|
||||
|
||||
v1 = v1Bak.clone();
|
||||
v2 = v2Bak.clone();
|
||||
|
||||
document.write("<ol>");
|
||||
var v6 = Tools.cross(new THREE.Vector3(1,0,0), new THREE.Vector3(0,1,0));
|
||||
test(Tools.equals(v6, new THREE.Vector3(0,0,1)));
|
||||
test(Tools.equals(v1, v1Bak));
|
||||
test(Tools.equals(v2, v2Bak));
|
||||
document.write('</ol>');
|
||||
|
||||
v1 = v1Bak.clone();
|
||||
v2 = v2Bak.clone();
|
||||
|
||||
document.write("<ol>");
|
||||
for (var lambda = 0; lambda < 5; lambda += 0.5)
|
||||
{
|
||||
var v7 = Tools.mul(v1, lambda);
|
||||
test(Tools.equals(v7, new THREE.Vector3(v1Bak.x*lambda, v1Bak.y*lambda, v1Bak.z*lambda)));
|
||||
v1 = v1Bak.clone();
|
||||
v2 = v2Bak.clone();
|
||||
var v8 = Tools.mul(v1, lambda);
|
||||
test(Tools.equals(v8, new THREE.Vector3(v1Bak.x*lambda, v1Bak.y*lambda, v1Bak.z*lambda)));
|
||||
v1 = v1Bak.clone();
|
||||
v2 = v2Bak.clone();
|
||||
|
||||
// Try into v1
|
||||
v1 = Tools.mul(v1, lambda);
|
||||
test(Tools.equals(v1, new THREE.Vector3(v1Bak.x*lambda, v1Bak.y*lambda, v1Bak.z*lambda)));
|
||||
v1 = v1Bak.clone();
|
||||
v2 = v2Bak.clone();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
97
js/bouncing/BouncingMain.js
Normal file
97
js/bouncing/BouncingMain.js
Normal file
@@ -0,0 +1,97 @@
|
||||
var renderer, scene, camera, controls, cube, container, plane, mouse= {x:0, y:0};
|
||||
var raycaster;
|
||||
var objects = [];
|
||||
var container_size = new Object();
|
||||
container_size.width = 1067;
|
||||
container_size.height = 600;
|
||||
|
||||
init();
|
||||
animate();
|
||||
|
||||
function init() {
|
||||
// on initialise le moteur de rendu
|
||||
container = document.getElementById('container');
|
||||
container.style.height = container_size.height + 'px';
|
||||
container.style.width = container_size.width + 'px';
|
||||
renderer = new THREE.WebGLRenderer({alpha:"true"});
|
||||
renderer.setSize(container_size.width, container_size.height);
|
||||
renderer.shadowMapEnabled = true;
|
||||
document.getElementById('container').appendChild(renderer.domElement);
|
||||
|
||||
// on initialise la scène
|
||||
scene = new THREE.Scene();
|
||||
raycaster = new THREE.Raycaster();
|
||||
|
||||
// init light
|
||||
var directional_light = new THREE.DirectionalLight(0xffffff);
|
||||
directional_light.position.set(1, 0.5, 1).normalize();
|
||||
directional_light.castShadow = true;
|
||||
scene.add(directional_light);
|
||||
|
||||
var ambient_light = new THREE.AmbientLight(0x444444);
|
||||
scene.add(ambient_light);
|
||||
|
||||
// on initialise la camera que l’on place ensuite sur la scène
|
||||
camera = new Camera(50, container_size.width / container_size.height, 1, 10000);
|
||||
scene.add(camera);
|
||||
|
||||
window.addEventListener('resize', onWindowResize, false);
|
||||
|
||||
container.addEventListener('mousedown', click, false);
|
||||
|
||||
// on créé un cube au quel on définie un matériau puis on l’ajoute à la scène
|
||||
cube = new BouncingCube(200, {color: "red"});
|
||||
plane = new Plane(1000,1000);
|
||||
plane.translate(0,0,-100);
|
||||
|
||||
cube.addToScene(scene);
|
||||
plane.addToScene(scene);
|
||||
|
||||
objects.push(cube);
|
||||
objects.push(plane);
|
||||
}
|
||||
|
||||
function animate() {
|
||||
// on appelle la fonction animate() récursivement à chaque frame
|
||||
requestAnimationFrame(animate);
|
||||
|
||||
cube.update();
|
||||
|
||||
camera.update();
|
||||
camera.look();
|
||||
|
||||
renderer.render(scene, camera);
|
||||
|
||||
}
|
||||
|
||||
function onWindowResize() {
|
||||
camera.aspect = container.offsetWidth / container.offsetHeight;
|
||||
camera.updateProjectionMatrix();
|
||||
|
||||
renderer.setSize(container.offsetWidth, container.offsetHeight);
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
|
||||
function click(event) {
|
||||
mouse.x = ( ( event.clientX - renderer.domElement.offsetLeft ) / renderer.domElement.width ) * 2 - 1;
|
||||
mouse.y = - ( ( event.clientY - renderer.domElement.offsetTop ) / renderer.domElement.height ) * 2 + 1;
|
||||
|
||||
// For this alternate method, set the canvas position *fixed*; set top > 0, set left > 0; padding must be 0; margin > 0 is OK
|
||||
//mouse.x = ( ( event.clientX - container.offsetLeft ) / container.clientWidth ) * 2 - 1;
|
||||
//mouse.y = - ( ( event.clientY - container.offsetTop ) / container.clientHeight ) * 2 + 1;
|
||||
|
||||
var vector = new THREE.Vector3(mouse.x, mouse.y, 0.5);
|
||||
vector.unproject(camera);
|
||||
|
||||
raycaster.set(camera.position, vector.sub(camera.position).normalize());
|
||||
|
||||
intersects = raycaster.intersectObjects(scene.children);
|
||||
|
||||
if ( intersects.length > 0 ) {
|
||||
for (var i in intersects) {
|
||||
if (intersects[i].object.id === cube.mesh.id) {
|
||||
cube.speed.z = 300;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
116
js/multisphere/MultiSphere.js
Normal file
116
js/multisphere/MultiSphere.js
Normal file
@@ -0,0 +1,116 @@
|
||||
var mesh_number = 25;
|
||||
var renderer, scene, camera, controls, cube, container, plane, mouse= {x:0, y:0};
|
||||
var raycaster;
|
||||
var objects = [];
|
||||
var spheres = new Array(mesh_number);
|
||||
var visible = 0;
|
||||
|
||||
var loader;
|
||||
|
||||
var container_size = new Object();
|
||||
container_size.width = 1067;
|
||||
container_size.height = 600;
|
||||
|
||||
init();
|
||||
animate();
|
||||
|
||||
function init() {
|
||||
// on initialise le moteur de rendu
|
||||
container = document.getElementById('container');
|
||||
container.style.height = container_size.height + 'px';
|
||||
container.style.width = container_size.width + 'px';
|
||||
renderer = new THREE.WebGLRenderer({alpha:"true"});
|
||||
renderer.setSize(container_size.width, container_size.height);
|
||||
renderer.shadowMapEnabled = true;
|
||||
document.getElementById('container').appendChild(renderer.domElement);
|
||||
|
||||
// on initialise la scène
|
||||
scene = new THREE.Scene();
|
||||
raycaster = new THREE.Raycaster();
|
||||
|
||||
// init light
|
||||
var directional_light = new THREE.DirectionalLight(0xffffff);
|
||||
directional_light.position.set(1, 0.5, 1).normalize();
|
||||
directional_light.castShadow = true;
|
||||
scene.add(directional_light);
|
||||
|
||||
var ambient_light = new THREE.AmbientLight(0x444444);
|
||||
scene.add(ambient_light);
|
||||
|
||||
// on initialise la camera que l’on place ensuite sur la scène
|
||||
camera = new Camera(50, container_size.width / container_size.height, 1, 10000);
|
||||
scene.add(camera);
|
||||
|
||||
window.addEventListener('resize', onWindowResize, false);
|
||||
|
||||
container.addEventListener('mousedown', click, false);
|
||||
|
||||
// Création d'un objloader
|
||||
loader = new THREE.OBJLoader();
|
||||
|
||||
for (var i = 0; i < mesh_number; i++) {
|
||||
// Capture of i
|
||||
// I am pretty good
|
||||
(function(i) {
|
||||
loader.load(static_path + 'data/spheres/' + (i+1) + '.obj', function (object) {
|
||||
object.traverse(function (child) {
|
||||
if (child instanceof THREE.Mesh ) {
|
||||
child.material.color.setHex(0xff0000);
|
||||
child.up = new THREE.Vector3(0,0,1);
|
||||
child.geometry.computeFaceNormals();
|
||||
child.geometry.computeVertexNormals();
|
||||
}
|
||||
});
|
||||
spheres[i] = object;
|
||||
scene.add(object);
|
||||
if (i != 0)
|
||||
hide(object);
|
||||
});
|
||||
})(i);
|
||||
}
|
||||
|
||||
|
||||
plane = new Plane(1000,1000);
|
||||
plane.translate(0,0,-100);
|
||||
plane.addToScene(scene);
|
||||
}
|
||||
|
||||
function animate() {
|
||||
// on appelle la fonction animate() récursivement à chaque frame
|
||||
requestAnimationFrame(animate);
|
||||
|
||||
camera.update();
|
||||
camera.look();
|
||||
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
|
||||
function onWindowResize() {
|
||||
camera.aspect = container.offsetWidth / container.offsetHeight;
|
||||
camera.updateProjectionMatrix();
|
||||
|
||||
renderer.setSize(container.offsetWidth, container.offsetHeight);
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
|
||||
function click(event) {
|
||||
++visible;
|
||||
visible %= spheres.length;
|
||||
|
||||
console.log('Mesh ', visible + 1, ' out of ', spheres.length, ' : ', spheres[visible].children[0].geometry.attributes.position.array.length, ' vertices (with duplication...)');
|
||||
|
||||
// hide everything except visible
|
||||
for (var i in spheres)
|
||||
{
|
||||
hide(spheres[i]);
|
||||
}
|
||||
show(spheres[visible]);
|
||||
}
|
||||
|
||||
function hide(object) {
|
||||
object.traverse(function ( object ) { object.visible = false; } );
|
||||
}
|
||||
|
||||
function show(object) {
|
||||
object.traverse(function ( object ) { object.visible = true; } );
|
||||
}
|
||||
252
js/prototype/ArrowCamera.js
vendored
Normal file
252
js/prototype/ArrowCamera.js
vendored
Normal file
@@ -0,0 +1,252 @@
|
||||
// Initialization
|
||||
|
||||
// class camera extends THREE.PerspectiveCamera
|
||||
var ArrowCamera = function(arg1, arg2, arg3, arg4, position, target) {
|
||||
THREE.PerspectiveCamera.apply(this, arguments);
|
||||
|
||||
// Set Position
|
||||
if (position === undefined) {
|
||||
this.position = new THREE.Vector3(0,0,5);
|
||||
} else {
|
||||
this.position.x = position.x;
|
||||
this.position.y = position.y;
|
||||
this.position.z = position.z;
|
||||
}
|
||||
|
||||
if (target === undefined)
|
||||
target = new THREE.Vector3(0,0,0);
|
||||
|
||||
var direction = target.clone();
|
||||
direction.sub(this.position);
|
||||
direction.normalize();
|
||||
|
||||
this.center = this.position.clone();
|
||||
this.center.sub(direction);
|
||||
|
||||
this.target = this.position.clone();
|
||||
this.target.add(Tools.mul(direction,20));
|
||||
|
||||
|
||||
this.arrow = new THREE.Mesh(new THREE.Geometry(), new THREE.MeshLambertMaterial({color: 0x0000ff, side:THREE.BackSide}));
|
||||
|
||||
this.size = 0.4;
|
||||
|
||||
this.object3D = new THREE.Object3D();
|
||||
this.object3D.add(this.initExtremity());
|
||||
this.object3D.add(this.arrow);
|
||||
|
||||
this.fullArrow = false;
|
||||
|
||||
}
|
||||
ArrowCamera.prototype = Object.create(THREE.PerspectiveCamera.prototype);
|
||||
ArrowCamera.prototype.constructor = ArrowCamera;
|
||||
|
||||
ArrowCamera.prototype.check = function() {
|
||||
this.object3D.traverse(function(obj) {
|
||||
if (obj instanceof THREE.Mesh)
|
||||
obj.material.color.setHex(0x663366);
|
||||
});
|
||||
}
|
||||
|
||||
ArrowCamera.prototype.initExtremity = function() {
|
||||
var geometry = new THREE.Geometry();
|
||||
|
||||
var direction = this.target.clone();
|
||||
direction.sub(this.position);
|
||||
direction.normalize();
|
||||
|
||||
var left = Tools.cross(direction, this.up);
|
||||
var other = Tools.cross(direction, left);
|
||||
|
||||
|
||||
left.normalize();
|
||||
other.normalize();
|
||||
left = Tools.mul(left, this.size);
|
||||
other = Tools.mul(other, this.size);
|
||||
|
||||
geometry.vertices.push(Tools.sum( Tools.sum( this.position, left), other),
|
||||
Tools.diff(Tools.sum( this.position, other), left),
|
||||
Tools.diff(Tools.diff(this.position, left), other),
|
||||
Tools.sum( Tools.diff(this.position, other), left),
|
||||
Tools.sum(this.position, direction)
|
||||
);
|
||||
|
||||
geometry.faces.push(new THREE.Face3(0,2,1), // new THREE.Face3(0,2,1),
|
||||
new THREE.Face3(0,3,2), // new THREE.Face3(0,3,2)
|
||||
new THREE.Face3(4,1,2),
|
||||
new THREE.Face3(4,0,1),
|
||||
new THREE.Face3(4,3,0),
|
||||
new THREE.Face3(4,2,3)
|
||||
);
|
||||
|
||||
geometry.computeFaceNormals();
|
||||
|
||||
var material = new THREE.MeshLambertMaterial({
|
||||
color : 0x0000ff,
|
||||
transparent : true,
|
||||
opacity : 0.5,
|
||||
side: THREE.FrontSide
|
||||
});
|
||||
|
||||
this.mesh = new THREE.Mesh(geometry, material);
|
||||
return this.mesh;
|
||||
}
|
||||
|
||||
// Update function
|
||||
ArrowCamera.prototype.update = function(mainCamera) {
|
||||
// Compute distance between center of camera and position
|
||||
dist = Tools.norm2(Tools.diff(mainCamera.position, this.center));
|
||||
|
||||
var low_bound = 1;
|
||||
var high_bound = 5;
|
||||
var new_value;
|
||||
|
||||
if (dist < low_bound) {
|
||||
new_value = 0;
|
||||
}
|
||||
else if (dist > high_bound) {
|
||||
new_value = 1;
|
||||
}
|
||||
else {
|
||||
new_value = (dist - low_bound)/(high_bound - low_bound);
|
||||
}
|
||||
|
||||
// Update opacity
|
||||
this.object3D.traverse(function(elt) {
|
||||
if (elt instanceof THREE.Mesh) {
|
||||
elt.material.transparent = new_value < 0.9;
|
||||
elt.material.opacity = new_value;
|
||||
|
||||
if (new_value < 0.1)
|
||||
elt.material.transparent = elt.visible = false;
|
||||
}
|
||||
});
|
||||
|
||||
this.regenerateArrow(mainCamera);
|
||||
}
|
||||
|
||||
ArrowCamera.prototype.regenerateArrow = function(mainCamera) {
|
||||
var vertices = new Array();
|
||||
|
||||
// First point of curve
|
||||
var f0 = mainCamera.position.clone();
|
||||
f0.add(Tools.mul(Tools.sum(new THREE.Vector3(0,-0.5,0), Tools.diff(this.target, this.position).normalize()),2));
|
||||
|
||||
// Last point of curve
|
||||
var f1 = this.position.clone();
|
||||
|
||||
// Last derivative of curve
|
||||
var fp1 = Tools.diff(this.target, this.position);
|
||||
fp1.normalize();
|
||||
fp1.multiplyScalar(2);
|
||||
|
||||
// Camera direction
|
||||
var dir = Tools.diff(this.position, mainCamera.position);
|
||||
dir.normalize();
|
||||
|
||||
if (fp1.dot(dir) < -0.5) {
|
||||
// Regen polynom with better stuff
|
||||
// var new_dir = Tools.cross(Tools.diff(this.position, mainCamera.position).normalize(), mainCamera.up);
|
||||
// new_dir.multiplyScalar(new_dir.dot(fp1) < 0 ? 1 : -1);
|
||||
// new_dir.add(dir);
|
||||
// new_dir.add(dir);
|
||||
// new_dir.multiplyScalar(2);
|
||||
// f0.add(new_dir);
|
||||
|
||||
if (mainCamera.position.y > this.position.y) {
|
||||
f0.add(new THREE.Vector3(0,2,0));
|
||||
} else {
|
||||
f0.add(new THREE.Vector3(0,-2,0));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fp1.multiplyScalar(4);
|
||||
|
||||
var hermite = new Hermite.special.Polynom(f0, f1, fp1);
|
||||
|
||||
var up = this.up.clone();
|
||||
var point;
|
||||
var deriv;
|
||||
var limit = this.fullArrow ? 0.1 : 0.3;
|
||||
|
||||
// for (var i = this.fullArrow ? 0 : 0.5; i <= 1.001; i += 0.05) {
|
||||
for (var i = 1; i > limit; i -= 0.1) {
|
||||
point = hermite.eval(i);
|
||||
deriv = hermite.prime(i);
|
||||
up.cross(deriv);
|
||||
up.cross(deriv);
|
||||
up.multiplyScalar(-1);
|
||||
up.normalize();
|
||||
|
||||
var coeff = this.size / 2;
|
||||
var left = Tools.cross(up, deriv); left.normalize(); left.multiplyScalar(coeff);
|
||||
var other = Tools.cross(deriv, left); other.normalize(); other.multiplyScalar(coeff);
|
||||
|
||||
vertices.push(
|
||||
Tools.sum(Tools.sum(point, left), other),
|
||||
Tools.sum(Tools.diff(point, left), other),
|
||||
Tools.diff(point, Tools.sum(other,left)),
|
||||
Tools.sum(Tools.diff(point, other), left)
|
||||
);
|
||||
}
|
||||
|
||||
this.arrow.geometry.vertices = vertices;
|
||||
|
||||
if (this.arrow.geometry.faces.length == 0) {
|
||||
var faces = new Array();
|
||||
|
||||
for (var i = 0; i < vertices.length - 4; i+= 4) {
|
||||
faces.push(new THREE.Face3(i,i+1,i+5),new THREE.Face3(i,i+5,i+4),
|
||||
new THREE.Face3(i+1,i+2,i+6),new THREE.Face3(i+1,i+6,i+5),
|
||||
new THREE.Face3(i+2,i+3,i+7),new THREE.Face3(i+2,i+7,i+6),
|
||||
new THREE.Face3(i,i+7,i+3), new THREE.Face3(i,i+4,i+7));
|
||||
}
|
||||
|
||||
var len = vertices.length;
|
||||
faces.push(new THREE.Face3(len-4,len-3,len-2), new THREE.Face3(len-4,len-2,len-1));
|
||||
|
||||
var max = 0;
|
||||
for (var i = 0; i < faces.length; i++) {
|
||||
max = Math.max(max, faces[i].a, faces[i].b, faces[i].c);
|
||||
}
|
||||
console.log(max + '/' + len);
|
||||
|
||||
|
||||
this.arrow.geometry.faces = faces;
|
||||
this.arrow.geometry.facesNeedUpdate = true;
|
||||
}
|
||||
|
||||
// this.arrow.geometry.mergeVertices();
|
||||
this.arrow.geometry.computeFaceNormals();
|
||||
// this.arrow.geometry.computeVertexNormals();
|
||||
this.arrow.geometry.computeBoundingSphere();
|
||||
|
||||
// this.arrow.geometry.vertices[0] = new THREE.Vector3(); // mainCamera.position.clone();
|
||||
// this.arrow.geometry.vertices[1] = this.position.clone();
|
||||
|
||||
this.arrow.geometry.dynamic = true;
|
||||
this.arrow.geometry.verticesNeedUpdate = true;
|
||||
this.arrow.geometry.elementsNeedUpdate = true;
|
||||
this.arrow.geometry.groupsNeedUpdate = true;
|
||||
this.arrow.geometry.normalsNeedUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
// Look function
|
||||
ArrowCamera.prototype.look = function() {
|
||||
this.lookAt(this.target);
|
||||
}
|
||||
|
||||
ArrowCamera.prototype.addToScene = function(scene) {
|
||||
scene.add(this);
|
||||
scene.add(this.object3D);
|
||||
}
|
||||
|
||||
ArrowCamera.prototype.traverse = function(callback) {
|
||||
this.object3D.traverse(callback);
|
||||
}
|
||||
|
||||
ArrowCamera.prototype.containsObject = function(object) {
|
||||
return object.parent === this.object3D;
|
||||
}
|
||||
63
js/prototype/ButtonManager.js
vendored
Normal file
63
js/prototype/ButtonManager.js
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
var ButtonManager = function(cameras, previewer) {
|
||||
this.cameras = cameras;
|
||||
this.previewer = previewer;
|
||||
|
||||
this.showArrows = true;
|
||||
this.beenFullscreen = false;
|
||||
|
||||
this.fullscreenElement = document.getElementById('full');
|
||||
this.fullElement = document.getElementById('fullarrow');
|
||||
this.resetElement = document.getElementById('reset');
|
||||
this.undoElement = document.getElementById('undo');
|
||||
this.redoElement = document.getElementById('redo');
|
||||
|
||||
this.collisionElement = document.getElementById('collisions');
|
||||
this.showarrowsElement = document.getElementById('showarrows');
|
||||
|
||||
this.recommendationElement = document.getElementById('recommendation');
|
||||
|
||||
this.fullscreenElement.onclick = function() {fullscreen();};
|
||||
|
||||
(function(self) {
|
||||
self.undoElement.onclick = function() {self.cameras.mainCamera().undo(); self.updateElements();}
|
||||
self.redoElement.onclick = function() {self.cameras.mainCamera().redo(); self.updateElements();}
|
||||
|
||||
self.fullElement.onclick = function() {
|
||||
self.cameras.map(function(camera) {
|
||||
if (!(camera instanceof PointerCamera)) {
|
||||
camera.fullArrow = self.fullElement.checked;
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
self.collisionElement.onchange = function() {self.cameras.mainCamera().collisions = self.collisionElement.checked;}
|
||||
self.showarrowsElement.onchange = function() {self.showArrows = self.showarrowsElement.checked;}
|
||||
|
||||
self.resetElement.onclick = function() {
|
||||
// Reinit camera
|
||||
self.cameras.mainCamera().reset();
|
||||
}
|
||||
|
||||
self.recommendationElement.onchange = function() {
|
||||
previewer.fixedRecommendation(self.recommendationElement.checked);
|
||||
}
|
||||
})(this);
|
||||
|
||||
}
|
||||
|
||||
ButtonManager.prototype.updateElements = function() {
|
||||
// Update icon
|
||||
if (!this.cameras.mainCamera().undoable()) {
|
||||
this.undoElement.className = "btn btn-default";
|
||||
} else {
|
||||
this.undoElement.className = "btn btn-primary";
|
||||
}
|
||||
|
||||
if (!this.cameras.mainCamera().redoable()) {
|
||||
this.redoElement.className = "btn btn-default";
|
||||
} else {
|
||||
this.redoElement.className = "btn btn-primary";
|
||||
}
|
||||
}
|
||||
|
||||
93
js/prototype/Coin.js
vendored
Normal file
93
js/prototype/Coin.js
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
var Coin = function(x,y,z) {
|
||||
this.ready = false;
|
||||
this.got = false;
|
||||
this.init(x,y,z);
|
||||
}
|
||||
|
||||
var _toto = new Audio();
|
||||
Coin.extension = _toto.canPlayType("audio/x-vorbis") === "" ? ".ogg" : ".mp3";
|
||||
|
||||
Coin.prototype.init = function(x,y,z) {
|
||||
Coin.nextSound = new Audio(static_path + 'data/music/redcoins/1' + Coin.extension);
|
||||
if (Coin.BASIC_MESH !== null) {
|
||||
this.mesh = Coin.BASIC_MESH.clone();
|
||||
this.mesh.position.x = x;
|
||||
this.mesh.position.y = y;
|
||||
this.mesh.position.z = z;
|
||||
this.ready = true;
|
||||
this.mesh.raycastable = true;
|
||||
} else {
|
||||
(function(self,x,y,z) {
|
||||
setTimeout(function() {
|
||||
self.init(x,y,z);
|
||||
},1000);
|
||||
})(this,x,y,z);
|
||||
}
|
||||
}
|
||||
|
||||
Coin.prototype.addToScene = function(scene) {
|
||||
scene.add(this.mesh);
|
||||
}
|
||||
|
||||
Coin.prototype.update = function() {
|
||||
if (this.ready)
|
||||
(function(self) {
|
||||
self.update = function() {
|
||||
// self.mesh.rotation.y += 0.1;
|
||||
}
|
||||
})(this);
|
||||
}
|
||||
|
||||
Coin.prototype.get = function() {
|
||||
if (!this.got) {
|
||||
this.got = true;
|
||||
if (this.mesh) {
|
||||
this.mesh.visible = false;
|
||||
}
|
||||
Coin.total ++;
|
||||
Coin.nextSound.play();
|
||||
if (Coin.total === 9) {
|
||||
// You got the last coin
|
||||
var music = document.getElementById('music');
|
||||
var wasPlaying = !music.paused;
|
||||
music.pause();
|
||||
(function(music, wasPlaying) {
|
||||
setTimeout(function() {
|
||||
Coin.lastSound.play();
|
||||
(function(wasPlaying) {
|
||||
setTimeout(function() {
|
||||
if (wasPlaying) {
|
||||
music.play();
|
||||
}
|
||||
}, Coin.lastSound.duration*1000);
|
||||
})(wasPlaying);
|
||||
}, Coin.nextSound.duration*1000);
|
||||
})(music, wasPlaying);
|
||||
} else {
|
||||
Coin.nextSound = new Audio('/static/data/music/redcoins/' + Coin.total + Coin.extension);
|
||||
Coin.nextSound.preload = "auto";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Coin.lastSound = new Audio('/static/data/music/starappears' + Coin.extension);
|
||||
Coin.lastSound.preload = "auto";
|
||||
|
||||
Coin.total = 1;
|
||||
Coin.BASIC_MESH = null;
|
||||
|
||||
Coin._loader = new THREE.OBJLoader();
|
||||
Coin._loader.load(
|
||||
static_path + 'data/coin/Coin.obj',
|
||||
function(object) {
|
||||
object.traverse(function (mesh) {
|
||||
if (mesh instanceof THREE.Mesh) {
|
||||
mesh.scale.set(0.005,0.005,0.005);
|
||||
mesh.material.color.setHex(0xff0000);
|
||||
mesh.geometry.computeVertexNormals();
|
||||
mesh.raycastable = true;
|
||||
Coin.BASIC_MESH = mesh
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
9
js/prototype/FixedCamera.js
vendored
Normal file
9
js/prototype/FixedCamera.js
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// Initialization
|
||||
|
||||
// class camera extends THREE.PerspectiveCamera
|
||||
var FixedCamera = function(arg1, arg2, arg3, arg4, position, target) {
|
||||
ArrowCamera.apply(this, arguments);
|
||||
}
|
||||
FixedCamera.prototype = Object.create(ArrowCamera.prototype);
|
||||
FixedCamera.prototype.constructor = FixedCamera;
|
||||
|
||||
141
js/prototype/OldFixedCamera.js
vendored
Normal file
141
js/prototype/OldFixedCamera.js
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
// Initialization
|
||||
|
||||
// class camera extends THREE.PerspectiveCamera
|
||||
var OldFixedCamera = function(arg1, arg2, arg3, arg4, position, target) {
|
||||
THREE.PerspectiveCamera.apply(this, arguments);
|
||||
|
||||
// Set Position
|
||||
if (position === undefined) {
|
||||
this.position = new THREE.Vector3(0,0,5);
|
||||
} else {
|
||||
this.position.x = position.x;
|
||||
this.position.y = position.y;
|
||||
this.position.z = position.z;
|
||||
}
|
||||
|
||||
if (target === undefined)
|
||||
target = new THREE.Vector3(0,0,0);
|
||||
|
||||
var direction = target.clone();
|
||||
direction.sub(this.position);
|
||||
direction.normalize();
|
||||
|
||||
this.target = this.position.clone();
|
||||
this.target.add(Tools.mul(direction,10));
|
||||
// this.up = new THREE.Vector3(0,0,1);
|
||||
|
||||
// Compute corners
|
||||
|
||||
// Create the mesh to draw
|
||||
|
||||
var geometry = new THREE.Geometry();
|
||||
|
||||
var left = Tools.cross(direction, this.up);
|
||||
var other = Tools.cross(direction, left);
|
||||
left.normalize();
|
||||
other.normalize();
|
||||
left = Tools.mul(left, 1);
|
||||
other = Tools.mul(other, 1);
|
||||
|
||||
geometry.vertices.push(Tools.sum(Tools.sum(this.position, left), other),
|
||||
Tools.diff(Tools.sum(this.position, other),left),
|
||||
Tools.diff(Tools.diff(this.position, left),other),
|
||||
Tools.sum(Tools.diff(this.position, other), left)
|
||||
);
|
||||
|
||||
geometry.faces.push(new THREE.Face3(0,1,2), // new THREE.Face3(0,2,1),
|
||||
new THREE.Face3(0,2,3) // new THREE.Face3(0,3,2)
|
||||
);
|
||||
|
||||
(function(self, direction, left, other) {
|
||||
var material = new THREE.LineBasicMaterial({ color: '0x000000'});
|
||||
var geometry = new THREE.Geometry();
|
||||
var direction = Tools.mul(direction, -2);
|
||||
var target = Tools.sum(self.position, direction);
|
||||
// geometry.vertices.push(self.position, target);
|
||||
geometry.vertices.push(
|
||||
Tools.sum(Tools.sum(self.position, left), other),
|
||||
Tools.diff(Tools.sum(self.position, other),left),
|
||||
Tools.diff(Tools.diff(self.position, left),other),
|
||||
Tools.sum(Tools.diff(self.position, other), left),
|
||||
Tools.sum(Tools.sum(self.position, left), other),
|
||||
Tools.sum(Tools.diff(self.position, other), left),
|
||||
|
||||
Tools.sum(self.position, direction),
|
||||
Tools.sum(Tools.sum(self.position, left), other),
|
||||
|
||||
Tools.sum(self.position, direction),
|
||||
Tools.diff(Tools.sum(self.position, other),left),
|
||||
|
||||
Tools.sum(self.position, direction),
|
||||
Tools.diff(Tools.diff(self.position, left),other),
|
||||
|
||||
Tools.sum(self.position, direction),
|
||||
Tools.sum(Tools.diff(self.position, other), left)
|
||||
);
|
||||
|
||||
self.line = new THREE.Line(geometry, material);
|
||||
})(this, direction, left, other);
|
||||
|
||||
|
||||
var material = new THREE.MeshBasicMaterial({
|
||||
color : 0x0000ff,
|
||||
transparent : true,
|
||||
opacity : 1,
|
||||
side: THREE.DoubleSide
|
||||
});
|
||||
|
||||
this.mesh = new THREE.Mesh(geometry, material);
|
||||
this.mesh.raycastable = true;
|
||||
}
|
||||
OldFixedCamera.prototype = Object.create(THREE.PerspectiveCamera.prototype);
|
||||
OldFixedCamera.prototype.constructor = OldFixedCamera;
|
||||
|
||||
OldFixedCamera.prototype.check = function() {
|
||||
this.mesh.material.color.setHex(0x663366);
|
||||
}
|
||||
|
||||
// Update function
|
||||
OldFixedCamera.prototype.update = function(position) {
|
||||
// Compute distance between center of camera and position
|
||||
dist = Tools.norm2(Tools.diff(position.position, this.position));
|
||||
|
||||
var low_bound = 1;
|
||||
var high_bound = 5;
|
||||
var new_value;
|
||||
var max_value = 0.5;
|
||||
|
||||
if (dist < low_bound)
|
||||
new_value = 0;
|
||||
else if (dist > high_bound)
|
||||
new_value = max_value;
|
||||
else
|
||||
new_value = max_value * (dist - low_bound)/(high_bound - low_bound);
|
||||
|
||||
this.mesh.material.transparent = new_value < 0.9;
|
||||
this.mesh.material.opacity = new_value;
|
||||
|
||||
if (new_value < 0.1)
|
||||
this.mesh.material.transparent = this.mesh.visible = false;
|
||||
}
|
||||
|
||||
// Look function
|
||||
OldFixedCamera.prototype.look = function() {
|
||||
this.lookAt(this.target);
|
||||
}
|
||||
|
||||
OldFixedCamera.prototype.addToScene = function(scene) {
|
||||
scene.add(this);
|
||||
scene.add(this.mesh);
|
||||
scene.add(this.line);
|
||||
}
|
||||
|
||||
OldFixedCamera.prototype.traverse = function(callback) {
|
||||
callback(this.mesh);
|
||||
callback(this.line);
|
||||
}
|
||||
|
||||
OldFixedCamera.prototype.containsObject = function(object) {
|
||||
return object === this.mesh;
|
||||
}
|
||||
|
||||
79
js/prototype/Previewer.js
vendored
Normal file
79
js/prototype/Previewer.js
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
Math.clamp = Math.clamp || function(number, min, max) {
|
||||
return Math.max(Math.min(number, max), min);
|
||||
}
|
||||
|
||||
var Previewer = function(renderer) {
|
||||
this.domElement = document.createElement('canvas');
|
||||
this.ctx = this.domElement.getContext('2d');
|
||||
this.renderer = renderer;
|
||||
this.fixed = false;
|
||||
}
|
||||
|
||||
Previewer.prototype.render = function(prev, container_width, container_height) {
|
||||
var width, height, left, bottom;
|
||||
|
||||
if (prev.go) {
|
||||
width = Math.floor(container_width / 5);
|
||||
height = Math.floor(container_height / 5);
|
||||
if (!this.fixed) {
|
||||
left = Math.floor(prev.x - width/2);
|
||||
bottom = Math.floor(this.renderer.domElement.height - prev.y + height/5);
|
||||
|
||||
// Translate box if too high
|
||||
if (bottom + height > this.renderer.domElement.height) {
|
||||
bottom -= 7 * height / 5;
|
||||
}
|
||||
|
||||
// Translate box if too on the side
|
||||
left = Math.clamp(left, width / 5, this.renderer.domElement.width - 6 * width / 5);
|
||||
|
||||
} else {
|
||||
left = 0;
|
||||
bottom = 0;
|
||||
}
|
||||
|
||||
// Draw border
|
||||
var can_bottom = container_height - bottom - height ;
|
||||
this.ctx.strokeStyle = "#ffffff";
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(left-1, can_bottom);
|
||||
this.ctx.lineTo(left-1, can_bottom + height);
|
||||
this.ctx.lineTo(left + width-1, can_bottom + height);
|
||||
this.ctx.lineTo(left + width-1, can_bottom);
|
||||
this.ctx.closePath();
|
||||
this.ctx.stroke();
|
||||
|
||||
this.ctx.strokeStyle = "#000000";
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(left, can_bottom + 1);
|
||||
this.ctx.lineTo(left, can_bottom + height - 1);
|
||||
this.ctx.lineTo(left + width - 2 , can_bottom + height-1);
|
||||
this.ctx.lineTo(left + width - 2, can_bottom+1);
|
||||
this.ctx.closePath();
|
||||
this.ctx.stroke();
|
||||
|
||||
// Do render in previsualization
|
||||
prev.camera.look();
|
||||
this.renderer.setScissor(left, bottom, width, height);
|
||||
this.renderer.enableScissorTest(true);
|
||||
this.renderer.setViewport(left, bottom, width, height);
|
||||
this.renderer.render(scene, prev.camera);
|
||||
|
||||
if (!this.fixed) {
|
||||
this.clearNeeded = true;
|
||||
}
|
||||
} else if (this.fixed) {
|
||||
this.clearNeeded = true;
|
||||
}
|
||||
}
|
||||
|
||||
Previewer.prototype.clear = function() {
|
||||
if (this.clearNeeded) {
|
||||
this.domElement.width = this.domElement.width;
|
||||
this.clearNeeded = false;
|
||||
}
|
||||
}
|
||||
|
||||
Previewer.prototype.fixedRecommendation = function(bool) {
|
||||
this.fixed = bool;
|
||||
}
|
||||
201
js/prototype/ReplayCamera.js
vendored
Normal file
201
js/prototype/ReplayCamera.js
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
// class camera extends THREE.PerspectiveCamera
|
||||
var ReplayCamera = function() {
|
||||
THREE.PerspectiveCamera.apply(this, arguments);
|
||||
|
||||
this.started = false;
|
||||
this.counter = 0;
|
||||
|
||||
this.position = new THREE.Vector3();
|
||||
this.target = new THREE.Vector3();
|
||||
this.new_position = new THREE.Vector3();
|
||||
this.new_target = new THREE.Vector3();
|
||||
|
||||
var id = params.get.id;
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "/prototype/replay_info/" + id, true);
|
||||
|
||||
(function(self) {
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState == 4 && xhr.status == 200) {
|
||||
self.path = JSON.parse(xhr.responseText);
|
||||
self.reset();
|
||||
self.started = true;
|
||||
self.nextEvent();
|
||||
}
|
||||
}
|
||||
})(this);
|
||||
xhr.send();
|
||||
|
||||
// Set Position
|
||||
this.theta = Math.PI;
|
||||
this.phi = Math.PI;
|
||||
|
||||
|
||||
}
|
||||
ReplayCamera.prototype = Object.create(THREE.PerspectiveCamera.prototype);
|
||||
ReplayCamera.prototype.constructor = ReplayCamera;
|
||||
|
||||
ReplayCamera.prototype.look = function() {
|
||||
this.lookAt(this.target);
|
||||
}
|
||||
|
||||
// Update function
|
||||
ReplayCamera.prototype.update = function(time) {
|
||||
if (this.started) {
|
||||
if (this.event.type == 'camera') {
|
||||
this.cameraMotion(time);
|
||||
} else if (this.event.type == 'previousnext') {
|
||||
this.linearMotion(time / 5);
|
||||
} else if (this.event.type == 'arrow') {
|
||||
this.hermiteMotion(time);
|
||||
} else if (this.event.type == 'coin') {
|
||||
// Nothing to do
|
||||
} else if (this.event.type == 'reset') {
|
||||
// Nothing to do
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReplayCamera.prototype.linearMotion = function(time) {
|
||||
var tmp = Tools.sum(Tools.mul(this.old_position, 1-this.t), Tools.mul(this.new_position, this.t));
|
||||
this.position.x = tmp.x;
|
||||
this.position.y = tmp.y;
|
||||
this.position.z = tmp.z;
|
||||
this.t += 0.1 * time / 20;
|
||||
|
||||
if (this.t > 1) {
|
||||
this.nextEvent();
|
||||
}
|
||||
}
|
||||
|
||||
ReplayCamera.prototype.cameraMotion = function(time) {
|
||||
|
||||
var tmp = Tools.sum(Tools.mul(this.old_position, 1-this.t), Tools.mul(this.new_position, this.t));
|
||||
this.position.x = tmp.x;
|
||||
this.position.y = tmp.y;
|
||||
this.position.z = tmp.z;
|
||||
this.target = Tools.sum(Tools.mul(this.old_target, 1-this.t), Tools.mul(this.new_target, this.t));
|
||||
this.t += 1 / (((new Date(this.path[this.counter].time)).getTime() - (new Date(this.path[this.counter-1].time)).getTime()) / 20);
|
||||
|
||||
if (this.t > 1) {
|
||||
this.nextEvent();
|
||||
}
|
||||
}
|
||||
|
||||
ReplayCamera.prototype.hermiteMotion = function(time) {
|
||||
var eval = this.hermitePosition.eval(this.t);
|
||||
this.position.x = eval.x;
|
||||
this.position.y = eval.y;
|
||||
this.position.z = eval.z;
|
||||
|
||||
this.target = Tools.sum(this.position, this.hermiteAngles.eval(this.t));
|
||||
|
||||
this.t += 0.01 * time / 20;
|
||||
|
||||
if (this.t > 1) {
|
||||
this.nextEvent();
|
||||
}
|
||||
}
|
||||
|
||||
ReplayCamera.prototype.nextEvent = function() {
|
||||
this.counter++;
|
||||
|
||||
// Finished
|
||||
if (this.counter >= this.path.length) {
|
||||
this.started = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.event = this.path[this.counter];
|
||||
|
||||
if (this.event.type == 'camera') {
|
||||
this.move(this.event);
|
||||
} else if (this.event.type == 'coin') {
|
||||
coins[this.event.id].get();
|
||||
// Wait a little before launching nextEvent
|
||||
(function(self) {
|
||||
setTimeout(function() {
|
||||
self.nextEvent();
|
||||
},500);
|
||||
})(this);
|
||||
} else if (this.event.type == 'arrow') {
|
||||
this.moveHermite(cameras.cameras[this.event.id]);
|
||||
} else if (this.event.type == 'reset') {
|
||||
this.reset();
|
||||
(function (self) {
|
||||
setTimeout(function() {
|
||||
self.nextEvent();
|
||||
},500);
|
||||
})(this);
|
||||
} else if (this.event.type == 'previousnext') {
|
||||
this.move(this.event);
|
||||
} else if (this.event.type == 'hovered') {
|
||||
this.nextEvent();
|
||||
}
|
||||
}
|
||||
|
||||
ReplayCamera.prototype.reset = function() {
|
||||
this.resetBobomb();
|
||||
this.moving = false;
|
||||
this.movingHermite = false;
|
||||
// this.position.copy(new THREE.Vector3(-8.849933489419644, 9.050627639459208, 0.6192960680432451));
|
||||
// this.target.copy(new THREE.Vector3(17.945323228767702, -15.156828589982375, -16.585740412769756));
|
||||
// this.anglesFromVectors();
|
||||
}
|
||||
|
||||
ReplayCamera.prototype.resetBobomb = function() {
|
||||
this.position.copy(new THREE.Vector3(34.51854618261728,10.038879540840306,-21.772598201888613));
|
||||
this.target.copy(new THREE.Vector3(-2.593404107644737,8.039712770013185,-6.983870133675925));
|
||||
this.anglesFromVectors();
|
||||
}
|
||||
|
||||
ReplayCamera.prototype.vectorsFromAngles = function() {
|
||||
// Update direction
|
||||
this.forward.y = Math.sin(this.phi);
|
||||
|
||||
var cos = Math.cos(this.phi);
|
||||
this.forward.z = cos * Math.cos(this.theta);
|
||||
this.forward.x = cos * Math.sin(this.theta);
|
||||
this.forward.normalize();
|
||||
|
||||
}
|
||||
|
||||
ReplayCamera.prototype.anglesFromVectors = function() {
|
||||
// Update phi and theta so that return to reality does not hurt
|
||||
var forward = Tools.diff(this.target, this.position);
|
||||
forward.normalize();
|
||||
|
||||
this.phi = Math.asin(forward.y);
|
||||
|
||||
// Don't know why this line works... But thanks Thierry-san and
|
||||
// Bastien because it seems to work...
|
||||
this.theta = Math.atan2(forward.x, forward.z);
|
||||
}
|
||||
|
||||
ReplayCamera.prototype.move = function(otherCamera) {
|
||||
this.moving = true;
|
||||
this.old_target = this.target.clone();
|
||||
this.old_position = this.position.clone();
|
||||
this.new_target = new THREE.Vector3(otherCamera.target.x, otherCamera.target.y, otherCamera.target.z);
|
||||
this.new_position = new THREE.Vector3(otherCamera.position.x, otherCamera.position.y, otherCamera.position.z);
|
||||
this.t = 0;
|
||||
|
||||
}
|
||||
|
||||
ReplayCamera.prototype.moveHermite = function(otherCamera) {
|
||||
this.movingHermite = true;
|
||||
this.t = 0;
|
||||
|
||||
this.hermitePosition = new Hermite.special.Polynom(
|
||||
this.position.clone(),
|
||||
otherCamera.position.clone(),
|
||||
Tools.mul(Tools.diff(otherCamera.target, otherCamera.position).normalize(),4)
|
||||
);
|
||||
|
||||
this.hermiteAngles = new Hermite.special.Polynom(
|
||||
Tools.diff(this.target, this.position),
|
||||
Tools.diff(otherCamera.target, otherCamera.position),
|
||||
new THREE.Vector3()
|
||||
);
|
||||
}
|
||||
74
js/prototype/ReverseCamera.js
vendored
Normal file
74
js/prototype/ReverseCamera.js
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
// Initialization
|
||||
|
||||
// class camera extends THREE.PerspectiveCamera
|
||||
var ReverseCamera = function(arg1, arg2, arg3, arg4, position, target) {
|
||||
ArrowCamera.apply(this, arguments);
|
||||
}
|
||||
ReverseCamera.prototype = Object.create(ArrowCamera.prototype);
|
||||
ReverseCamera.prototype.constructor = ReverseCamera;
|
||||
|
||||
// Overload init
|
||||
ReverseCamera.prototype.initExtremity = function() {
|
||||
var geometry = new THREE.Geometry();
|
||||
|
||||
var direction = this.target.clone();
|
||||
direction.sub(this.position);
|
||||
direction.normalize();
|
||||
|
||||
var left = Tools.cross(direction, this.up);
|
||||
var other = Tools.cross(direction, left);
|
||||
|
||||
left.normalize();
|
||||
other.normalize();
|
||||
left = Tools.mul(left, this.size / 2 );
|
||||
other = Tools.mul(other, this.size / 2);
|
||||
|
||||
var pyramidCenter = Tools.diff(this.position, Tools.mul(direction,0.25))
|
||||
geometry.vertices.push(
|
||||
Tools.sum( Tools.sum( this.position, left), other),
|
||||
Tools.diff(Tools.sum( this.position, other), left),
|
||||
Tools.diff(Tools.diff(this.position, left), other),
|
||||
Tools.sum( Tools.diff(this.position, other), left),
|
||||
|
||||
Tools.sum( Tools.sum( this.position, left), other),
|
||||
Tools.diff(Tools.sum( this.position, other), left),
|
||||
Tools.diff(Tools.diff(this.position, left), other),
|
||||
Tools.sum( Tools.diff(this.position, other), left)
|
||||
// Tools.diff(this.position, direction)
|
||||
);
|
||||
|
||||
var lambda = 0.6;
|
||||
for (var i = 0; i < 4; i++)
|
||||
geometry.vertices[i] = Tools.mul(Tools.diff(geometry.vertices[i], Tools.mul(pyramidCenter,lambda)), 1/(1-lambda));
|
||||
|
||||
|
||||
geometry.faces.push(new THREE.Face3(2,0,1), // new THREE.Face3(0,2,1),
|
||||
new THREE.Face3(3,0,2), // new THREE.Face3(0,3,2)
|
||||
|
||||
new THREE.Face3(1,0,4),
|
||||
new THREE.Face3(1,4,5),
|
||||
|
||||
new THREE.Face3(2,1,5),
|
||||
new THREE.Face3(2,5,6),
|
||||
|
||||
new THREE.Face3(7,2,6),
|
||||
new THREE.Face3(7,3,2),
|
||||
|
||||
new THREE.Face3(3,7,4),
|
||||
new THREE.Face3(3,4,0)
|
||||
|
||||
);
|
||||
|
||||
geometry.computeFaceNormals();
|
||||
|
||||
var material = new THREE.MeshLambertMaterial({
|
||||
color : 0x0000ff,
|
||||
transparent : true,
|
||||
opacity : 0.5,
|
||||
side: THREE.FrontSide
|
||||
});
|
||||
|
||||
this.mesh = new THREE.Mesh(geometry, material);
|
||||
return this.mesh;
|
||||
|
||||
}
|
||||
336
js/prototype/initScene.js
vendored
Normal file
336
js/prototype/initScene.js
vendored
Normal file
@@ -0,0 +1,336 @@
|
||||
// Define RecommendedCamera if not defined
|
||||
var RecommendedCamera = RecommendedCamera || FixedCamera;
|
||||
|
||||
function initPeachCastle(scene, collidableObjects, loader, static_path) {
|
||||
// Create loader if not already done
|
||||
if (loader === undefined) {
|
||||
loader = new THREE.OBJMTLLoader();
|
||||
}
|
||||
|
||||
// Try to guess the path to static files
|
||||
if (static_path === undefined) {
|
||||
static_path = "/static/";
|
||||
}
|
||||
|
||||
loader.load(
|
||||
static_path + 'data/castle/princess peaches castle (outside).obj',
|
||||
static_path + 'data/castle/princess peaches castle (outside).mtl',
|
||||
function ( object ) {
|
||||
object.up = new THREE.Vector3(0,0,1);
|
||||
scene.add(object);
|
||||
collidableObjects.push(object);
|
||||
object.traverse(function (object) {
|
||||
if (object instanceof THREE.Mesh) {
|
||||
object.geometry.mergeVertices();
|
||||
object.geometry.computeVertexNormals();
|
||||
object.material.side = THREE.DoubleSide;
|
||||
object.raycastable = true;
|
||||
if (object.material.name === 'Material.103_princess_peaches_cast') {
|
||||
object.material.transparent = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
loader.load(
|
||||
static_path + 'data/first/Floor 1.obj',
|
||||
static_path + 'data/first/Floor 1.mtl',
|
||||
function ( object ) {
|
||||
object.position.z -= 10.9;
|
||||
object.position.y += 0.555;
|
||||
object.position.x += 3.23;
|
||||
|
||||
var theta = 0.27;
|
||||
object.rotation.y = Math.PI - theta;
|
||||
|
||||
object.up = new THREE.Vector3(0,0,1);
|
||||
scene.add(object);
|
||||
collidableObjects.push(object);
|
||||
object.traverse(function (object) {
|
||||
if (object instanceof THREE.Mesh) {
|
||||
object.material.side = THREE.DoubleSide;
|
||||
object.geometry.mergeVertices();
|
||||
object.geometry.computeVertexNormals();
|
||||
object.raycastable = true;
|
||||
if (object.material.name === 'Material.054_777F0E0B_c.bmp' ||
|
||||
object.material.name === 'Material.061_5C3492AB_c.bmp' ) {
|
||||
object.material.transparent = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function initZeldaScene(scene, collidableObjects, loader, static_path) {
|
||||
// Create loader if not already done
|
||||
if (loader === undefined) {
|
||||
loader = new THREE.OBJMTLLoader();
|
||||
}
|
||||
|
||||
// Try to guess the path to static files
|
||||
if (static_path === undefined) {
|
||||
static_path = "/static/";
|
||||
}
|
||||
|
||||
loader.load(
|
||||
static_path + 'data/zelda/Island.obj',
|
||||
static_path + 'data/zelda/Island.mtl',
|
||||
function ( object ) {
|
||||
scene.add(object);
|
||||
collidableObjects.push(object);
|
||||
object.scale.set(0.01,0.01,0.01);
|
||||
object.traverse(function (object) {
|
||||
if (object instanceof THREE.Mesh) {
|
||||
object.geometry.mergeVertices();
|
||||
object.geometry.computeVertexNormals();
|
||||
object.material.side = THREE.DoubleSide;
|
||||
object.raycastable = true;
|
||||
if (object.material.name === 'm0') {
|
||||
object.material.transparent = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
// loader.load(
|
||||
// static_path + 'data/zelda/Sea.obj',
|
||||
// static_path + 'data/zelda/Sea.mtl',
|
||||
// function ( object ) {
|
||||
// scene.add(object);
|
||||
// collidableObjects.push(object);
|
||||
// object.scale.set(0.01,0.01,0.01);
|
||||
// object.traverse(function (object) {
|
||||
// if (object instanceof THREE.Mesh) {
|
||||
// object.geometry.mergeVertices();
|
||||
// object.geometry.computeVertexNormals();
|
||||
// object.raycastable = true;
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// );
|
||||
|
||||
// loader.load(
|
||||
// static_path + 'data/zelda/Window Lights.obj',
|
||||
// static_path + 'data/zelda/Window Lights.mtl',
|
||||
// function ( object ) {
|
||||
// scene.add(object);
|
||||
// collidableObjects.push(object);
|
||||
// object.scale.set(0.01,0.01,0.01);
|
||||
// object.traverse(function (object) {
|
||||
// if (object instanceof THREE.Mesh) {
|
||||
// object.geometry.mergeVertices();
|
||||
// object.geometry.computeVertexNormals();
|
||||
// object.raycastable = true;
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// );
|
||||
}
|
||||
|
||||
|
||||
function createPeachCameras(width, height) {
|
||||
var cams = [];
|
||||
|
||||
var createCamera = function(position, target) {
|
||||
return new RecommendedCamera(
|
||||
50,
|
||||
width / height,
|
||||
1,
|
||||
100000,
|
||||
position,
|
||||
target
|
||||
);
|
||||
}
|
||||
|
||||
cams.push(createCamera(
|
||||
new THREE.Vector3(-3.349895207953063, 5.148106346852601, 0.3365943929701533),
|
||||
new THREE.Vector3(13.114421714865292, -7.783476327687569, -33.74713248359852)
|
||||
));
|
||||
|
||||
cams.push(createCamera(
|
||||
new THREE.Vector3(4.659399030971226, 1.018674883050052597, -2.578139604982815),
|
||||
new THREE.Vector3(-16.08800293200113, -28.8795632312717, -19.165379404919797)
|
||||
));
|
||||
|
||||
cams.push(createCamera(
|
||||
new THREE.Vector3(2.625389073616235, 1.2252620948239699, -4.818718135555419),
|
||||
new THREE.Vector3(-19.756833131355208, -16.20027570329664, -33.02132017177813)
|
||||
));
|
||||
|
||||
cams.push(createCamera(
|
||||
new THREE.Vector3(1.3304975149911331, 0.4836093721106701, -8.60618907952783),
|
||||
new THREE.Vector3(-1.7713635815431914, 6.271997833695163, -48.06341930106774)
|
||||
));
|
||||
|
||||
cams.push(createCamera(
|
||||
new THREE.Vector3(1.2976081760482443, 1.1520399813234647, -10.258148122402845),
|
||||
new THREE.Vector3(-26.00651734173549, -9.19681009597505, -37.596510029925945)
|
||||
));
|
||||
|
||||
cams.push(createCamera(
|
||||
new THREE.Vector3(0.15727187830660858, 2.7251137440572855, -5.84333603646124),
|
||||
new THREE.Vector3(19.33738702531091, -13.614383891308975, -36.91010284556961)
|
||||
));
|
||||
|
||||
return cams;
|
||||
}
|
||||
|
||||
function initBobombScene(scene, collidableObjects, loader, static_path) {
|
||||
// Create loader if not already done
|
||||
if (loader === undefined) {
|
||||
loader = new THREE.OBJMTLLoader();
|
||||
}
|
||||
|
||||
// Try to guess the path to static files
|
||||
if (static_path === undefined) {
|
||||
static_path = "/static/";
|
||||
}
|
||||
|
||||
loader.load(
|
||||
static_path + 'data/bobomb/bobomb battlefeild.obj',
|
||||
static_path + 'data/bobomb/bobomb battlefeild.mtl',
|
||||
function ( object ) {
|
||||
// object.position.z -= 10.9;
|
||||
// object.position.y += 0.555;
|
||||
// object.position.x += 3.23;
|
||||
|
||||
var theta = 0.27;
|
||||
object.rotation.y = Math.PI - theta;
|
||||
|
||||
object.up = new THREE.Vector3(0,0,1);
|
||||
collidableObjects.push(object);
|
||||
scene.add(object);
|
||||
object.traverse(function (object) {
|
||||
if (object instanceof THREE.Mesh) {
|
||||
object.raycastable = true;
|
||||
object.material.side = THREE.DoubleSide;
|
||||
object.geometry.mergeVertices();
|
||||
object.geometry.computeVertexNormals();
|
||||
if (object.material.name === 'Material.071_574B138E_c.bmp' ||
|
||||
object.material.name === 'Material.070_41A41EE3_c.bmp') {
|
||||
object.material.transparent = true;
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
// loader.load(
|
||||
// static_path + 'data/star/GrandStar.obj',
|
||||
// static_path + 'data/star/GrandStar.mtl',
|
||||
// function ( object ) {
|
||||
// object.position.z -= 10.9;
|
||||
// object.position.y += 0.555;
|
||||
// object.position.x += 3.23;
|
||||
|
||||
// var theta = 0.27;
|
||||
// object.rotation.y = Math.PI - theta;
|
||||
|
||||
// object.up = new THREE.Vector3(0,0,1);
|
||||
// scene.add(object);
|
||||
// collidableObjects.push(object);
|
||||
// object.traverse(function (object) {
|
||||
// if (object instanceof THREE.Mesh) {
|
||||
// object.scale.set(0.005,0.005,0.005);
|
||||
// object.position.x = 13;
|
||||
// object.position.z = -35;
|
||||
// object.position.y = 30;
|
||||
|
||||
// object.rotation.z = Math.PI/2;
|
||||
// object.rotation.x = Math.PI/2;
|
||||
// object.rotation.y = Math.PI;
|
||||
// object.material.side = THREE.DoubleSide;
|
||||
// object.geometry.mergeVertices();
|
||||
// object.geometry.computeVertexNormals();
|
||||
// object.raycastable = true;
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//);
|
||||
}
|
||||
|
||||
function createBobombCoins() {
|
||||
var coins = [];
|
||||
|
||||
coins.push(
|
||||
new Coin(-1.6204001515660262,12.245208850063094,-24.871861611322934),
|
||||
new Coin(23.509767766131876,13.6929075780209,-6.1716274892265615),
|
||||
new Coin(34.797219873325524,13.088500612704706,-2.1784858128827413),
|
||||
new Coin(-23.255456493345882,15.763954882327724,-11.08029248078497),
|
||||
new Coin(-7.238094745133173,12.95460420281499,-3.1009487490121885),
|
||||
new Coin(-17.10578612221326,24.17871082944758,-11.574224169812915),
|
||||
new Coin(-12.418656949661646,17.09780294217035,32.472022253887665),
|
||||
new Coin(7.132802719121488,8.802400710545713,22.258165594421055)
|
||||
);
|
||||
|
||||
return coins;
|
||||
}
|
||||
|
||||
function createBobombCameras(width, height) {
|
||||
var cams = [];
|
||||
|
||||
var createCamera = function(position, target) {
|
||||
return new RecommendedCamera(
|
||||
50,
|
||||
width / height,
|
||||
1,
|
||||
100000,
|
||||
position,
|
||||
target
|
||||
);
|
||||
}
|
||||
|
||||
cams.push(
|
||||
createCamera(
|
||||
new THREE.Vector3(37.24445046448742,17.56004329173052,-13.432945825465112),
|
||||
new THREE.Vector3(15.446296842638255,0.7142524861838169,15.568085721947512)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(-24.10987782946019,26.75997424452833,-24.7814217620827),
|
||||
new THREE.Vector3(-13.724964120740987,14.939165978074758,11.993869660150779)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(7.162458619916293,18.414234017280627,-10.871480453809644),
|
||||
new THREE.Vector3(-27.47061192698706,3.9199238382137196,2.9294396939998144)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(19.741775033926334,14.132046557015727,-25.338452829449857),
|
||||
new THREE.Vector3(-18.0898892760213,1.5191520612050162,-28.449733590966297)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(-13.484471970922971,20.25938194278451,-30.850247430073622),
|
||||
new THREE.Vector3(-42.04654352929252,-7.608886431102082,-28.099304657929874)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(23.58849177613168,18.628351213754488,31.516769692916675),
|
||||
new THREE.Vector3(8.319765065757787,-0.5486703304136178,-0.09189730426033549)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(5.068708131530766,11.201320390433953,9.77462743108436),
|
||||
new THREE.Vector3(9.20744154720096,3.8549750522404134,48.87580511010085)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(4.18086580540298,16.54831275414988,29.96253548469186),
|
||||
new THREE.Vector3(-17.059296481928556,3.408610856102113,-1.2817238286325505)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(-44.56340663230823,22.567957426093283,14.856920056929788),
|
||||
new THREE.Vector3(-20.052660826451827,7.556450599683849,42.67558290835663)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(11.29580093093769,15.03666008708929,31.377195488571406),
|
||||
new THREE.Vector3(-28.288314738873957,13.648654387264967,25.794075678265735)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(28.438969076366728,18.888756501203087,26.694456000440766),
|
||||
new THREE.Vector3(-5.369166248035665,2.54925886583683,12.909289954623416)
|
||||
)
|
||||
);
|
||||
|
||||
return cams;
|
||||
|
||||
}
|
||||
279
js/prototype/main.js
vendored
Normal file
279
js/prototype/main.js
vendored
Normal file
@@ -0,0 +1,279 @@
|
||||
// Disable scrolling
|
||||
window.onscroll = function () { window.scrollTo(0, 0); };
|
||||
|
||||
var mesh_number = 25;
|
||||
var renderer, scene, controls, cube, container, plane, mouse= {x:0, y:0};
|
||||
var bigmesh;
|
||||
var raycaster;
|
||||
var objects = [];
|
||||
var cameras, cameraSelecter;
|
||||
var spheres = new Array(mesh_number);
|
||||
var visible = 0;
|
||||
var stats;
|
||||
var previewer;
|
||||
|
||||
var loader;
|
||||
var coins;
|
||||
var beenFullscreen = false;
|
||||
var isFullscreen = false;
|
||||
var previousTime;
|
||||
|
||||
var main_section = document.getElementById('main-section');
|
||||
var offset = function() {
|
||||
return
|
||||
document.getElementById('nav').offsetHeight
|
||||
+ document.getElementById('main-div').offsetHeight;
|
||||
}
|
||||
|
||||
console.log(document.getElementById('main-div').offsetHeight);
|
||||
var container_size = {
|
||||
width: function() { if (!isFullscreen) return main_section.clientWidth; else return screen.width;},
|
||||
height: function() {
|
||||
if (!isFullscreen)
|
||||
return main_section.clientHeight
|
||||
- document.getElementById('nav').offsetHeight
|
||||
- document.getElementById('main-div').offsetHeight;
|
||||
else
|
||||
return screen.height;
|
||||
}
|
||||
};
|
||||
|
||||
console.log(container_size.width(), container_size.height());
|
||||
|
||||
init();
|
||||
animate();
|
||||
|
||||
function init() {
|
||||
// Collidable objects to prevent camera from traversing objects
|
||||
var collidableObjects = new Array();
|
||||
|
||||
// Initialize renderer
|
||||
container = document.getElementById('container');
|
||||
container.style.height = container_size.height() + 'px';
|
||||
container.style.width = container_size.width() + 'px';
|
||||
renderer = new THREE.WebGLRenderer({alpha:true, antialias:true});
|
||||
renderer.setSize(container_size.width(), container_size.height());
|
||||
// renderer.setSize(container_size.width(), container_size.height());
|
||||
renderer.shadowMapEnabled = true;
|
||||
renderer.setClearColor(0x87ceeb);
|
||||
|
||||
// Initialize previewer
|
||||
previewer = new Previewer(renderer);
|
||||
previewer.domElement.style.position ="absolute";
|
||||
previewer.domElement.style.cssFloat = 'top-left';
|
||||
previewer.domElement.width = container_size.width();
|
||||
previewer.domElement.height = container_size.height();
|
||||
|
||||
// Initialize scene
|
||||
scene = new THREE.Scene();
|
||||
|
||||
// Initialize stats counter
|
||||
stats = new Stats();
|
||||
stats.setMode(0);
|
||||
stats.domElement.style.position = 'absolute';
|
||||
stats.domElement.style.cssFloat = "top-left";
|
||||
|
||||
// Add elements to page
|
||||
container.appendChild( stats.domElement );
|
||||
container.appendChild(previewer.domElement);
|
||||
container.appendChild(renderer.domElement);
|
||||
|
||||
// init light
|
||||
var directional_light = new THREE.DirectionalLight(0xdddddd);
|
||||
directional_light.position.set(1, 2.5, 1).normalize();
|
||||
directional_light.castShadow = false;
|
||||
scene.add(directional_light);
|
||||
|
||||
var ambient_light = new THREE.AmbientLight(0x555555);
|
||||
scene.add(ambient_light);
|
||||
|
||||
// Initialize pointer camera
|
||||
var camera1 = new PointerCamera(50, container_size.width() / container_size.height(), 0.01, 100000, container);
|
||||
camera1.speed = 0.005;
|
||||
camera1.resetBobomb();
|
||||
camera1.save();
|
||||
scene.add(camera1);
|
||||
|
||||
// Collisions
|
||||
camera1.collidableObjects = collidableObjects;
|
||||
|
||||
|
||||
// Initialize recommendations
|
||||
var otherCams = createBobombCameras(container_size.width(), container_size.height());
|
||||
cameras = new CameraContainer(camera1, otherCams);
|
||||
otherCams.forEach(function(cam) { cam.addToScene(scene); });
|
||||
|
||||
// Initalize loader
|
||||
var loader = new THREE.OBJMTLLoader();
|
||||
|
||||
// Load scene
|
||||
// initPeachCastle(scene, collidableObjects, loader, static_path);
|
||||
initBobombScene(scene, collidableObjects, loader, static_path);
|
||||
coins = createBobombCoins();
|
||||
|
||||
setTimeout(function() {coins.forEach(function(coin) { coin.addToScene(scene);})}, 1000);
|
||||
|
||||
// Add listeners
|
||||
initListeners();
|
||||
}
|
||||
|
||||
function initListeners() {
|
||||
window.addEventListener('resize', onWindowResize, false);
|
||||
|
||||
// Transmit click event to camera selecter
|
||||
container.addEventListener('mousedown', function(event) {
|
||||
if (event.which == 1)
|
||||
cameraSelecter.click(event);
|
||||
}, false
|
||||
);
|
||||
|
||||
// Update camera selecter when mouse moved
|
||||
container.addEventListener('mousemove', function(event) {
|
||||
cameraSelecter.update(event);
|
||||
}, false
|
||||
);
|
||||
|
||||
// Escape key to exit fullscreen mode
|
||||
document.addEventListener('keydown', function(event) { if (event.keyCode == 27) { stopFullscreen();} }, false);
|
||||
|
||||
// HTML Bootstrap buttons
|
||||
buttonManager = new ButtonManager(cameras, previewer);
|
||||
|
||||
// Camera selecter for hover and clicking recommendations
|
||||
cameraSelecter = new CameraSelecter(renderer, cameras, buttonManager);
|
||||
}
|
||||
|
||||
function fullscreen() {
|
||||
isFullscreen = true;
|
||||
|
||||
if (!beenFullscreen) {
|
||||
beenFullscreen = true;
|
||||
alert('To quit fullscren mode, type ESC key');
|
||||
}
|
||||
|
||||
container.style.position = "absolute";
|
||||
container.style.cssFloat = "top-left";
|
||||
container.style.top = "50px";
|
||||
container.style.bottom = "0px";
|
||||
container.style.left = "0px";
|
||||
container.style.right = "0px";
|
||||
container.style.width="";
|
||||
container.style.height="";
|
||||
container.style.overflow = "hidden";
|
||||
|
||||
// canvas.style.position = "absolute";
|
||||
// canvas.style.cssFloat = "top-left";
|
||||
// canvas.style.top = "0px";
|
||||
// canvas.style.bottom = "0px";
|
||||
// canvas.style.left = "0px";
|
||||
// canvas.style.right = "0px";
|
||||
// canvas.width=window.innerWidth;
|
||||
// canvas.height=window.innerHeight;
|
||||
// canvas.style.overflow = "hidden";
|
||||
|
||||
onWindowResize();
|
||||
}
|
||||
|
||||
function stopFullscreen() {
|
||||
isFullscreen = false;
|
||||
|
||||
container.style.position = "";
|
||||
container.style.cssFloat = "";
|
||||
container.style.top = "";
|
||||
container.style.bottom = "";
|
||||
container.style.left = "";
|
||||
container.style.right = "";
|
||||
container.style.width = container_size.width() + "px";
|
||||
container.style.height = container_size.height() + "px";
|
||||
|
||||
// canvas.style.position = "";
|
||||
// canvas.style.cssFloat = "";
|
||||
// canvas.style.top = "";
|
||||
// canvas.style.bottom = "";
|
||||
// canvas.style.left = "";
|
||||
// canvas.style.right = "";
|
||||
// canvas.width = container_size.width();
|
||||
// canvas.height = container_size.height();
|
||||
// canvas.style.overflow = "";
|
||||
|
||||
onWindowResize();
|
||||
}
|
||||
|
||||
function render() {
|
||||
cameraSelecter.update();
|
||||
|
||||
// Update recommendations (set raycastable if shown)
|
||||
var transform = buttonManager.showArrows ? show : hide;
|
||||
cameras.map(function(camera) {
|
||||
if (camera instanceof RecommendedCamera) {
|
||||
transform(camera);
|
||||
|
||||
camera.traverse(function(elt) {
|
||||
elt.raycastable = buttonManager.showArrows;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Update coins
|
||||
coins.forEach(function(coin) { coin.update(); });
|
||||
|
||||
// Update main camera
|
||||
var currentTime = Date.now() - previousTime;
|
||||
cameras.updateMainCamera(isNaN(currentTime) ? 20 : currentTime);
|
||||
previousTime = Date.now();
|
||||
|
||||
// Update the recommendations
|
||||
cameras.update(cameras.mainCamera());
|
||||
|
||||
|
||||
// Set current position of camera
|
||||
cameras.look();
|
||||
|
||||
var left = 0, bottom = 0, width = container_size.width(), height = container_size.height();
|
||||
renderer.setScissor(left, bottom, width, height);
|
||||
renderer.enableScissorTest(true);
|
||||
renderer.setViewport(left, bottom, width, height);
|
||||
renderer.render(scene, cameras.mainCamera());
|
||||
|
||||
// Remove borders of preview
|
||||
previewer.clear();
|
||||
|
||||
// Hide arrows in recommendation
|
||||
cameras.map(function(camera) { if (camera instanceof RecommendedCamera) hide(camera); });
|
||||
|
||||
// Render preview
|
||||
previewer.render(cameraSelecter.prev, container_size.width(), container_size.height());
|
||||
}
|
||||
|
||||
function animate() {
|
||||
// Render each frame
|
||||
requestAnimationFrame(animate);
|
||||
|
||||
// stats count the number of frames per second
|
||||
stats.begin();
|
||||
render();
|
||||
stats.end();
|
||||
}
|
||||
|
||||
function onWindowResize() {
|
||||
|
||||
container.style.width = container_size.width() + "px";
|
||||
container.style.height = container_size.height() + "px";
|
||||
|
||||
previewer.domElement.width = container_size.width();
|
||||
previewer.domElement.height = container_size.height();
|
||||
|
||||
renderer.setSize(container_size.width(), container_size.height());
|
||||
cameras.forEach(function(camera) {camera.aspect = container_size.width() / container_size.height();});
|
||||
cameras.forEach(function(camera) {camera.updateProjectionMatrix();});
|
||||
render();
|
||||
}
|
||||
|
||||
function hide(object) {
|
||||
object.traverse(function(object) {object.visible = false;});
|
||||
}
|
||||
|
||||
function show(object) {
|
||||
object.traverse(function(object) {object.visible = true;});
|
||||
}
|
||||
|
||||
109
js/prototype/raycasterTools.js
vendored
Normal file
109
js/prototype/raycasterTools.js
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
var CameraSelecter = function(renderer, cameras, buttonManager) {
|
||||
this.raycaster = new THREE.Raycaster();
|
||||
this.renderer = renderer;
|
||||
this.mouse = {};
|
||||
this.cameras = cameras;
|
||||
this.prev = {};
|
||||
this.buttonManager = buttonManager;
|
||||
}
|
||||
|
||||
CameraSelecter.prototype.pointedCamera = function() {
|
||||
var returnCamera;
|
||||
|
||||
var x = ( this.mouse.x / this.renderer.domElement.width ) * 2 - 1;
|
||||
var y = - (this.mouse.y / this.renderer.domElement.height) * 2 + 1;
|
||||
|
||||
var camera = this.cameras.mainCamera();
|
||||
|
||||
var vector = new THREE.Vector3(x, y, 0.5);
|
||||
vector.unproject(camera);
|
||||
|
||||
this.raycaster.set(camera.position, vector.sub(camera.position).normalize());
|
||||
|
||||
var intersects = this.raycaster.intersectObjects(scene.children, true);
|
||||
|
||||
if ( intersects.length > 0 ) {
|
||||
var minDistance;
|
||||
var bestIndex;
|
||||
|
||||
// Looking for cameras
|
||||
for (i in intersects) {
|
||||
if (intersects[i].object.raycastable && !(intersects[i].object instanceof THREE.Line)) {
|
||||
if ((intersects[i].distance > 0.5 && minDistance === undefined) || (intersects[i].distance < minDistance )) {
|
||||
if (!(intersects[i].object instanceof THREE.Mesh && intersects[i].object.material.opacity < 0.1)) {
|
||||
minDistance = intersects[i].distance;
|
||||
bestIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bestIndex !== undefined) {
|
||||
// if (this.cameras.getById(intersects[bestIndex].object.parent.id) !== undefined) {
|
||||
var obj = intersects[bestIndex].object;
|
||||
|
||||
for (var coin in coins) {
|
||||
if (obj === coins[coin].mesh) {
|
||||
return coins[coin];
|
||||
}
|
||||
}
|
||||
this.currentPointedCamera = this.cameras.getByObject(intersects[bestIndex].object);
|
||||
return this.currentPointedCamera;
|
||||
// }
|
||||
}
|
||||
}
|
||||
this.currentPointedCamera = null;
|
||||
}
|
||||
|
||||
CameraSelecter.prototype.update = function(event) {
|
||||
if (event !== undefined) {
|
||||
this.mouse.x = event.offsetX == undefined ? event.layerX : event.offsetX;
|
||||
this.mouse.y = event.offsetY == undefined ? event.layerY : event.offsetY;
|
||||
}
|
||||
|
||||
var previousCamera = this.currentPointedCamera;
|
||||
var hovered = this.pointedCamera(event);
|
||||
|
||||
if (hovered !== undefined && !(hovered instanceof Coin)) {
|
||||
if (hovered !== previousCamera) {
|
||||
// log it
|
||||
var event = new BD.Event.Hovered();
|
||||
event.start = true;
|
||||
event.arrow_id = cameras.cameras.indexOf(this.currentPointedCamera);
|
||||
event.send();
|
||||
|
||||
this.prev.x = this.mouse.x;
|
||||
this.prev.y = this.mouse.y;
|
||||
}
|
||||
this.prev.camera = hovered;
|
||||
this.prev.go = true;
|
||||
} else {
|
||||
if (this.prev.go) {
|
||||
// Log if previous was not null
|
||||
var event = new BD.Event.Hovered();
|
||||
event.start = false;
|
||||
event.arrow_id = null;
|
||||
event.send();
|
||||
}
|
||||
this.prev.go = false;
|
||||
}
|
||||
}
|
||||
|
||||
CameraSelecter.prototype.click = function(event) {
|
||||
var newCamera = this.pointedCamera(event);
|
||||
if (newCamera !== undefined && !(newCamera instanceof Coin)) {
|
||||
var event = new BD.Event.ArrowClicked();
|
||||
event.arrow_id = cameras.cameras.indexOf(newCamera);
|
||||
event.send();
|
||||
|
||||
newCamera.check();
|
||||
this.cameras.mainCamera().moveHermite(newCamera);
|
||||
buttonManager.updateElements();
|
||||
} else if (newCamera instanceof Coin) {
|
||||
// Coin found, notify server
|
||||
var event = new BD.Event.CoinClicked();
|
||||
event.coin_id = coins.indexOf(newCamera);
|
||||
event.send();
|
||||
newCamera.get();
|
||||
}
|
||||
}
|
||||
254
js/prototype/replay.js
vendored
Normal file
254
js/prototype/replay.js
vendored
Normal file
@@ -0,0 +1,254 @@
|
||||
// Disable scrolling
|
||||
window.onscroll = function () { window.scrollTo(0, 0); };
|
||||
|
||||
var mesh_number = 25;
|
||||
var renderer, scene, controls, cube, container, plane, mouse= {x:0, y:0};
|
||||
var bigmesh;
|
||||
var raycaster;
|
||||
var objects = [];
|
||||
var cameras, cameraSelecter;
|
||||
var spheres = new Array(mesh_number);
|
||||
var visible = 0;
|
||||
var stats;
|
||||
|
||||
var loader;
|
||||
var coins;
|
||||
var beenFullscreen = false;
|
||||
var isFullscreen = false;
|
||||
var previousTime;
|
||||
|
||||
var main_section = document.getElementById('main-section');
|
||||
var offset = function() {
|
||||
return
|
||||
document.getElementById('nav').offsetHeight
|
||||
+ document.getElementById('main-div').offsetHeight;
|
||||
}
|
||||
|
||||
console.log(document.getElementById('main-div').offsetHeight);
|
||||
var container_size = {
|
||||
width: function() { if (!isFullscreen) return main_section.clientWidth; else return screen.width;},
|
||||
height: function() {
|
||||
if (!isFullscreen)
|
||||
return main_section.clientHeight
|
||||
- document.getElementById('nav').offsetHeight
|
||||
- document.getElementById('main-div').offsetHeight;
|
||||
else
|
||||
return screen.height;
|
||||
}
|
||||
};
|
||||
|
||||
console.log(container_size.width(), container_size.height());
|
||||
|
||||
init();
|
||||
animate();
|
||||
|
||||
function init() {
|
||||
// Collidable objects to prevent camera from traversing objects
|
||||
var collidableObjects = new Array();
|
||||
|
||||
// Initialize renderer
|
||||
container = document.getElementById('container');
|
||||
container.style.height = container_size.height() + 'px';
|
||||
container.style.width = container_size.width() + 'px';
|
||||
renderer = new THREE.WebGLRenderer({alpha:true, antialias:true});
|
||||
renderer.setSize(container_size.width(), container_size.height());
|
||||
// renderer.setSize(container_size.width(), container_size.height());
|
||||
renderer.shadowMapEnabled = true;
|
||||
renderer.setClearColor(0x87ceeb);
|
||||
|
||||
// Initialize scene
|
||||
scene = new THREE.Scene();
|
||||
|
||||
// Initialize stats counter
|
||||
stats = new Stats();
|
||||
stats.setMode(0);
|
||||
stats.domElement.style.position = 'absolute';
|
||||
stats.domElement.style.cssFloat = "top-left";
|
||||
|
||||
// Add elements to page
|
||||
container.appendChild( stats.domElement );
|
||||
container.appendChild(renderer.domElement);
|
||||
|
||||
// init light
|
||||
var directional_light = new THREE.DirectionalLight(0xdddddd);
|
||||
directional_light.position.set(1, 2.5, 1).normalize();
|
||||
directional_light.castShadow = false;
|
||||
scene.add(directional_light);
|
||||
|
||||
var ambient_light = new THREE.AmbientLight(0x555555);
|
||||
scene.add(ambient_light);
|
||||
|
||||
// Initialize pointer camera
|
||||
var camera1 = new ReplayCamera(50, container_size.width() / container_size.height(), 0.01, 100000, container);
|
||||
scene.add(camera1);
|
||||
|
||||
// Initialize recommendations
|
||||
var otherCams = createBobombCameras(container_size.width(), container_size.height());
|
||||
cameras = new CameraContainer(camera1, otherCams);
|
||||
otherCams.forEach(function(cam) { cam.addToScene(scene); });
|
||||
|
||||
// Initalize loader
|
||||
var loader = new THREE.OBJMTLLoader();
|
||||
|
||||
// Load scene
|
||||
// initPeachCastle(scene, collidableObjects, loader, static_path);
|
||||
initBobombScene(scene, collidableObjects, loader, static_path);
|
||||
coins = createBobombCoins();
|
||||
|
||||
setTimeout(function() {coins.forEach(function(coin) { coin.addToScene(scene);})}, 1000);
|
||||
|
||||
// Add listeners
|
||||
initListeners();
|
||||
}
|
||||
|
||||
function initListeners() {
|
||||
window.addEventListener('resize', onWindowResize, false);
|
||||
|
||||
// Transmit click event to camera selecter
|
||||
container.addEventListener('mousedown', function(event) {
|
||||
if (event.which == 1)
|
||||
cameraSelecter.click(event);
|
||||
}, false
|
||||
);
|
||||
|
||||
// Update camera selecter when mouse moved
|
||||
container.addEventListener('mousemove', function(event) {
|
||||
cameraSelecter.update(event);
|
||||
}, false
|
||||
);
|
||||
|
||||
// Escape key to exit fullscreen mode
|
||||
document.addEventListener('keydown', function(event) { if (event.keyCode == 27) { stopFullscreen();} }, false);
|
||||
|
||||
// HTML Bootstrap buttons
|
||||
buttonManager = new ButtonManager(cameras);
|
||||
|
||||
// Camera selecter for hover and clicking recommendations
|
||||
cameraSelecter = new CameraSelecter(renderer, cameras, buttonManager);
|
||||
}
|
||||
|
||||
function fullscreen() {
|
||||
isFullscreen = true;
|
||||
|
||||
if (!beenFullscreen) {
|
||||
beenFullscreen = true;
|
||||
alert('To quit fullscren mode, type ESC key');
|
||||
}
|
||||
|
||||
container.style.position = "absolute";
|
||||
container.style.cssFloat = "top-left";
|
||||
container.style.top = "50px";
|
||||
container.style.bottom = "0px";
|
||||
container.style.left = "0px";
|
||||
container.style.right = "0px";
|
||||
container.style.width="";
|
||||
container.style.height="";
|
||||
container.style.overflow = "hidden";
|
||||
|
||||
// canvas.style.position = "absolute";
|
||||
// canvas.style.cssFloat = "top-left";
|
||||
// canvas.style.top = "0px";
|
||||
// canvas.style.bottom = "0px";
|
||||
// canvas.style.left = "0px";
|
||||
// canvas.style.right = "0px";
|
||||
// canvas.width=window.innerWidth;
|
||||
// canvas.height=window.innerHeight;
|
||||
// canvas.style.overflow = "hidden";
|
||||
|
||||
onWindowResize();
|
||||
}
|
||||
|
||||
function stopFullscreen() {
|
||||
isFullscreen = false;
|
||||
|
||||
container.style.position = "";
|
||||
container.style.cssFloat = "";
|
||||
container.style.top = "";
|
||||
container.style.bottom = "";
|
||||
container.style.left = "";
|
||||
container.style.right = "";
|
||||
container.style.width = container_size.width() + "px";
|
||||
container.style.height = container_size.height() + "px";
|
||||
|
||||
// canvas.style.position = "";
|
||||
// canvas.style.cssFloat = "";
|
||||
// canvas.style.top = "";
|
||||
// canvas.style.bottom = "";
|
||||
// canvas.style.left = "";
|
||||
// canvas.style.right = "";
|
||||
// canvas.width = container_size.width();
|
||||
// canvas.height = container_size.height();
|
||||
// canvas.style.overflow = "";
|
||||
|
||||
onWindowResize();
|
||||
}
|
||||
|
||||
function render() {
|
||||
cameraSelecter.update();
|
||||
|
||||
// Update recommendations (set raycastable if shown)
|
||||
var transform = buttonManager.showArrows ? show : hide;
|
||||
cameras.map(function(camera) {
|
||||
if (camera instanceof RecommendedCamera) {
|
||||
transform(camera);
|
||||
|
||||
camera.traverse(function(elt) {
|
||||
elt.raycastable = buttonManager.showArrows;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Update coins
|
||||
coins.forEach(function(coin) { coin.update(); });
|
||||
|
||||
// Update main camera
|
||||
var currentTime = Date.now() - previousTime;
|
||||
cameras.updateMainCamera(isNaN(currentTime) ? 20 : currentTime);
|
||||
previousTime = Date.now();
|
||||
|
||||
// Update the recommendations
|
||||
cameras.update(cameras.mainCamera());
|
||||
|
||||
|
||||
// Set current position of camera
|
||||
cameras.look();
|
||||
|
||||
var left = 0, bottom = 0, width = container_size.width(), height = container_size.height();
|
||||
renderer.setScissor(left, bottom, width, height);
|
||||
renderer.enableScissorTest(true);
|
||||
renderer.setViewport(left, bottom, width, height);
|
||||
renderer.render(scene, cameras.mainCamera());
|
||||
|
||||
// Hide arrows in recommendation
|
||||
cameras.map(function(camera) { if (camera instanceof RecommendedCamera) hide(camera); });
|
||||
}
|
||||
|
||||
function animate() {
|
||||
// Render each frame
|
||||
requestAnimationFrame(animate);
|
||||
|
||||
// stats count the number of frames per second
|
||||
stats.begin();
|
||||
render();
|
||||
stats.end();
|
||||
}
|
||||
|
||||
function onWindowResize() {
|
||||
|
||||
container.style.width = container_size.width() + "px";
|
||||
container.style.height = container_size.height() + "px";
|
||||
|
||||
renderer.setSize(container_size.width(), container_size.height());
|
||||
cameras.forEach(function(camera) {camera.aspect = container_size.width() / container_size.height();});
|
||||
cameras.forEach(function(camera) {camera.updateProjectionMatrix();});
|
||||
render();
|
||||
}
|
||||
|
||||
function hide(object) {
|
||||
object.traverse(function(object) {object.visible = false;});
|
||||
}
|
||||
|
||||
function show(object) {
|
||||
object.traverse(function(object) {object.visible = true;});
|
||||
}
|
||||
|
||||
87
js/stream/main.js
Normal file
87
js/stream/main.js
Normal file
@@ -0,0 +1,87 @@
|
||||
var mesh_number = 25;
|
||||
var renderer, scene, controls, cube, container, plane, mouse= {x:0, y:0}, sphere;
|
||||
var bigmesh;
|
||||
var raycaster;
|
||||
var objects = [];
|
||||
var spheres = new Array(mesh_number);
|
||||
var visible = 0;
|
||||
|
||||
var loader;
|
||||
|
||||
var container_size = {width: 1067, height: 600};
|
||||
|
||||
init();
|
||||
animate();
|
||||
|
||||
function init() {
|
||||
// on initialise le moteur de rendu
|
||||
container = document.getElementById('container');
|
||||
container.style.height = container_size.height + 'px';
|
||||
container.style.width = container_size.width + 'px';
|
||||
renderer = new THREE.WebGLRenderer({alpha:"true"});
|
||||
renderer.setSize(container_size.width, container_size.height);
|
||||
renderer.shadowMapEnabled = true;
|
||||
// renderer.setClearColor(0x000000);
|
||||
document.getElementById('container').appendChild(renderer.domElement);
|
||||
|
||||
// on initialise la scène
|
||||
scene = new THREE.Scene();
|
||||
raycaster = new THREE.Raycaster();
|
||||
|
||||
// init light
|
||||
var directional_light = new THREE.DirectionalLight(0x999999);
|
||||
directional_light.position.set(1, 0.5, 1).normalize();
|
||||
directional_light.castShadow = true;
|
||||
scene.add(directional_light);
|
||||
|
||||
var ambient_light = new THREE.AmbientLight(0x333333);
|
||||
scene.add(ambient_light);
|
||||
|
||||
// on initialise la camera que l’on place ensuite sur la scène
|
||||
camera = new Camera(50, container_size.width / container_size.height, 1, 100000);
|
||||
scene.add(camera);
|
||||
|
||||
window.addEventListener('resize', onWindowResize, false);
|
||||
container.addEventListener('mousedown', function() { } , false);
|
||||
|
||||
// Load the scene
|
||||
loader = new THREE.OBJLoader();
|
||||
sphere = new ProgessiveSphere(loader, params.get.res);
|
||||
|
||||
plane = new Plane(1000,1000);
|
||||
plane.translate(0,0,-100);
|
||||
plane.addToScene(scene);
|
||||
|
||||
}
|
||||
|
||||
function animate() {
|
||||
// on appelle la fonction animate() récursivement à chaque frame
|
||||
requestAnimationFrame(animate);
|
||||
|
||||
camera.update();
|
||||
camera.look();
|
||||
|
||||
sphere.addFace();
|
||||
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
|
||||
function onWindowResize() {
|
||||
camera.aspect = container.offsetWidth / container.offsetHeight;
|
||||
camera.updateProjectionMatrix();
|
||||
|
||||
renderer.setSize(container.offsetWidth, container.offsetHeight);
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
|
||||
function hide(object) {
|
||||
object.traverse(function(object) {object.visible = false;});
|
||||
}
|
||||
|
||||
function show(object) {
|
||||
object.traverse(function(object) {object.visible = true;});
|
||||
}
|
||||
|
||||
function click(event) {
|
||||
// Nope
|
||||
}
|
||||
35133
js/three.js
Normal file
35133
js/three.js
Normal file
File diff suppressed because one or more lines are too long
237
js/three/DDSLoader.js
Normal file
237
js/three/DDSLoader.js
Normal file
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
THREE.DDSLoader = function () {
|
||||
this._parser = THREE.DDSLoader.parse;
|
||||
};
|
||||
|
||||
THREE.DDSLoader.prototype = Object.create( THREE.CompressedTextureLoader.prototype );
|
||||
THREE.DDSLoader.prototype.constructor = THREE.DDSLoader;
|
||||
|
||||
THREE.DDSLoader.parse = function ( buffer, loadMipmaps ) {
|
||||
|
||||
var dds = { mipmaps: [], width: 0, height: 0, format: null, mipmapCount: 1 };
|
||||
|
||||
// Adapted from @toji's DDS utils
|
||||
// https://github.com/toji/webgl-texture-utils/blob/master/texture-util/dds.js
|
||||
|
||||
// All values and structures referenced from:
|
||||
// http://msdn.microsoft.com/en-us/library/bb943991.aspx/
|
||||
|
||||
var DDS_MAGIC = 0x20534444;
|
||||
|
||||
var DDSD_CAPS = 0x1,
|
||||
DDSD_HEIGHT = 0x2,
|
||||
DDSD_WIDTH = 0x4,
|
||||
DDSD_PITCH = 0x8,
|
||||
DDSD_PIXELFORMAT = 0x1000,
|
||||
DDSD_MIPMAPCOUNT = 0x20000,
|
||||
DDSD_LINEARSIZE = 0x80000,
|
||||
DDSD_DEPTH = 0x800000;
|
||||
|
||||
var DDSCAPS_COMPLEX = 0x8,
|
||||
DDSCAPS_MIPMAP = 0x400000,
|
||||
DDSCAPS_TEXTURE = 0x1000;
|
||||
|
||||
var DDSCAPS2_CUBEMAP = 0x200,
|
||||
DDSCAPS2_CUBEMAP_POSITIVEX = 0x400,
|
||||
DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800,
|
||||
DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000,
|
||||
DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000,
|
||||
DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000,
|
||||
DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000,
|
||||
DDSCAPS2_VOLUME = 0x200000;
|
||||
|
||||
var DDPF_ALPHAPIXELS = 0x1,
|
||||
DDPF_ALPHA = 0x2,
|
||||
DDPF_FOURCC = 0x4,
|
||||
DDPF_RGB = 0x40,
|
||||
DDPF_YUV = 0x200,
|
||||
DDPF_LUMINANCE = 0x20000;
|
||||
|
||||
function fourCCToInt32( value ) {
|
||||
|
||||
return value.charCodeAt(0) +
|
||||
(value.charCodeAt(1) << 8) +
|
||||
(value.charCodeAt(2) << 16) +
|
||||
(value.charCodeAt(3) << 24);
|
||||
|
||||
}
|
||||
|
||||
function int32ToFourCC( value ) {
|
||||
|
||||
return String.fromCharCode(
|
||||
value & 0xff,
|
||||
(value >> 8) & 0xff,
|
||||
(value >> 16) & 0xff,
|
||||
(value >> 24) & 0xff
|
||||
);
|
||||
}
|
||||
|
||||
function loadARGBMip( buffer, dataOffset, width, height ) {
|
||||
var dataLength = width * height * 4;
|
||||
var srcBuffer = new Uint8Array( buffer, dataOffset, dataLength );
|
||||
var byteArray = new Uint8Array( dataLength );
|
||||
var dst = 0;
|
||||
var src = 0;
|
||||
for ( var y = 0; y < height; y ++ ) {
|
||||
for ( var x = 0; x < width; x ++ ) {
|
||||
var b = srcBuffer[src]; src ++;
|
||||
var g = srcBuffer[src]; src ++;
|
||||
var r = srcBuffer[src]; src ++;
|
||||
var a = srcBuffer[src]; src ++;
|
||||
byteArray[dst] = r; dst ++; //r
|
||||
byteArray[dst] = g; dst ++; //g
|
||||
byteArray[dst] = b; dst ++; //b
|
||||
byteArray[dst] = a; dst ++; //a
|
||||
}
|
||||
}
|
||||
return byteArray;
|
||||
}
|
||||
|
||||
var FOURCC_DXT1 = fourCCToInt32("DXT1");
|
||||
var FOURCC_DXT3 = fourCCToInt32("DXT3");
|
||||
var FOURCC_DXT5 = fourCCToInt32("DXT5");
|
||||
|
||||
var headerLengthInt = 31; // The header length in 32 bit ints
|
||||
|
||||
// Offsets into the header array
|
||||
|
||||
var off_magic = 0;
|
||||
|
||||
var off_size = 1;
|
||||
var off_flags = 2;
|
||||
var off_height = 3;
|
||||
var off_width = 4;
|
||||
|
||||
var off_mipmapCount = 7;
|
||||
|
||||
var off_pfFlags = 20;
|
||||
var off_pfFourCC = 21;
|
||||
var off_RGBBitCount = 22;
|
||||
var off_RBitMask = 23;
|
||||
var off_GBitMask = 24;
|
||||
var off_BBitMask = 25;
|
||||
var off_ABitMask = 26;
|
||||
|
||||
var off_caps = 27;
|
||||
var off_caps2 = 28;
|
||||
var off_caps3 = 29;
|
||||
var off_caps4 = 30;
|
||||
|
||||
// Parse header
|
||||
|
||||
var header = new Int32Array( buffer, 0, headerLengthInt );
|
||||
|
||||
if ( header[ off_magic ] !== DDS_MAGIC ) {
|
||||
|
||||
console.error( 'THREE.DDSLoader.parse: Invalid magic number in DDS header.' );
|
||||
return dds;
|
||||
|
||||
}
|
||||
|
||||
if ( ! header[ off_pfFlags ] & DDPF_FOURCC ) {
|
||||
|
||||
console.error( 'THREE.DDSLoader.parse: Unsupported format, must contain a FourCC code.' );
|
||||
return dds;
|
||||
|
||||
}
|
||||
|
||||
var blockBytes;
|
||||
|
||||
var fourCC = header[ off_pfFourCC ];
|
||||
|
||||
var isRGBAUncompressed = false;
|
||||
|
||||
switch ( fourCC ) {
|
||||
|
||||
case FOURCC_DXT1:
|
||||
|
||||
blockBytes = 8;
|
||||
dds.format = THREE.RGB_S3TC_DXT1_Format;
|
||||
break;
|
||||
|
||||
case FOURCC_DXT3:
|
||||
|
||||
blockBytes = 16;
|
||||
dds.format = THREE.RGBA_S3TC_DXT3_Format;
|
||||
break;
|
||||
|
||||
case FOURCC_DXT5:
|
||||
|
||||
blockBytes = 16;
|
||||
dds.format = THREE.RGBA_S3TC_DXT5_Format;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
if ( header[off_RGBBitCount] == 32
|
||||
&& header[off_RBitMask]&0xff0000
|
||||
&& header[off_GBitMask]&0xff00
|
||||
&& header[off_BBitMask]&0xff
|
||||
&& header[off_ABitMask]&0xff000000 ) {
|
||||
isRGBAUncompressed = true;
|
||||
blockBytes = 64;
|
||||
dds.format = THREE.RGBAFormat;
|
||||
} else {
|
||||
console.error( 'THREE.DDSLoader.parse: Unsupported FourCC code ', int32ToFourCC( fourCC ) );
|
||||
return dds;
|
||||
}
|
||||
}
|
||||
|
||||
dds.mipmapCount = 1;
|
||||
|
||||
if ( header[ off_flags ] & DDSD_MIPMAPCOUNT && loadMipmaps !== false ) {
|
||||
|
||||
dds.mipmapCount = Math.max( 1, header[ off_mipmapCount ] );
|
||||
|
||||
}
|
||||
|
||||
//TODO: Verify that all faces of the cubemap are present with DDSCAPS2_CUBEMAP_POSITIVEX, etc.
|
||||
|
||||
dds.isCubemap = header[ off_caps2 ] & DDSCAPS2_CUBEMAP ? true : false;
|
||||
|
||||
dds.width = header[ off_width ];
|
||||
dds.height = header[ off_height ];
|
||||
|
||||
var dataOffset = header[ off_size ] + 4;
|
||||
|
||||
// Extract mipmaps buffers
|
||||
|
||||
var width = dds.width;
|
||||
var height = dds.height;
|
||||
|
||||
var faces = dds.isCubemap ? 6 : 1;
|
||||
|
||||
for ( var face = 0; face < faces; face ++ ) {
|
||||
|
||||
for ( var i = 0; i < dds.mipmapCount; i ++ ) {
|
||||
|
||||
if ( isRGBAUncompressed ) {
|
||||
var byteArray = loadARGBMip( buffer, dataOffset, width, height );
|
||||
var dataLength = byteArray.length;
|
||||
} else {
|
||||
var dataLength = Math.max( 4, width ) / 4 * Math.max( 4, height ) / 4 * blockBytes;
|
||||
var byteArray = new Uint8Array( buffer, dataOffset, dataLength );
|
||||
}
|
||||
|
||||
var mipmap = { "data": byteArray, "width": width, "height": height };
|
||||
dds.mipmaps.push( mipmap );
|
||||
|
||||
dataOffset += dataLength;
|
||||
|
||||
width = Math.max( width * 0.5, 1 );
|
||||
height = Math.max( height * 0.5, 1 );
|
||||
|
||||
}
|
||||
|
||||
width = dds.width;
|
||||
height = dds.height;
|
||||
|
||||
}
|
||||
|
||||
return dds;
|
||||
|
||||
};
|
||||
|
||||
441
js/three/MTLLoader.js
Normal file
441
js/three/MTLLoader.js
Normal file
@@ -0,0 +1,441 @@
|
||||
/**
|
||||
* Loads a Wavefront .mtl file specifying materials
|
||||
*
|
||||
* @author angelxuanchang
|
||||
*/
|
||||
|
||||
THREE.MTLLoader = function( baseUrl, options, crossOrigin ) {
|
||||
|
||||
this.baseUrl = baseUrl;
|
||||
this.options = options;
|
||||
this.crossOrigin = crossOrigin;
|
||||
|
||||
};
|
||||
|
||||
THREE.MTLLoader.prototype = {
|
||||
|
||||
constructor: THREE.MTLLoader,
|
||||
|
||||
load: function ( url, onLoad, onProgress, onError ) {
|
||||
|
||||
var scope = this;
|
||||
|
||||
var loader = new THREE.XHRLoader();
|
||||
loader.setCrossOrigin( this.crossOrigin );
|
||||
loader.load( url, function ( text ) {
|
||||
|
||||
onLoad( scope.parse( text ) );
|
||||
|
||||
}, onProgress, onError );
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Parses loaded MTL file
|
||||
* @param text - Content of MTL file
|
||||
* @return {THREE.MTLLoader.MaterialCreator}
|
||||
*/
|
||||
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.baseUrl, this.options );
|
||||
materialCreator.crossOrigin = this.crossOrigin
|
||||
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
|
||||
* invertTransparency: If transparency need to be inverted (inversion is needed if d = 0 is fully opaque)
|
||||
* Default: false (d = 1 is fully opaque)
|
||||
* @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,
|
||||
|
||||
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[ 1 ] === 0 ) {
|
||||
|
||||
// ignore
|
||||
|
||||
save = false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
|
||||
// According to MTL format (http://paulbourke.net/dataformats/mtl/):
|
||||
// d is dissolve for current material
|
||||
// factor of 1.0 is fully opaque, a factor of 0 is fully dissolved (completely transparent)
|
||||
|
||||
if ( this.options && this.options.invertTransparency ) {
|
||||
|
||||
value = 1 - value;
|
||||
|
||||
}
|
||||
|
||||
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 mat = this.materialsInfo[ materialName ];
|
||||
var params = {
|
||||
|
||||
name: materialName,
|
||||
side: this.side
|
||||
|
||||
};
|
||||
|
||||
for ( var prop in mat ) {
|
||||
|
||||
var value = mat[ prop ];
|
||||
|
||||
switch ( prop.toLowerCase() ) {
|
||||
|
||||
// Ns is material specular exponent
|
||||
|
||||
case 'kd':
|
||||
|
||||
// Diffuse color (color under white light) using RGB values
|
||||
|
||||
params[ 'diffuse' ] = new THREE.Color().fromArray( value );
|
||||
|
||||
break;
|
||||
|
||||
case 'ka':
|
||||
|
||||
// Ambient color (color under shadow) using RGB values
|
||||
|
||||
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
|
||||
|
||||
params[ 'map' ] = this.loadTexture( this.baseUrl + value );
|
||||
params[ 'map' ].wrapS = this.wrap;
|
||||
params[ 'map' ].wrapT = this.wrap;
|
||||
|
||||
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'] = value;
|
||||
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
|
||||
// According to MTL format (http://paulbourke.net/dataformats/mtl/):
|
||||
// d is dissolve for current material
|
||||
// factor of 1.0 is fully opaque, a factor of 0 is fully dissolved (completely transparent)
|
||||
|
||||
if ( value < 1 ) {
|
||||
|
||||
params['transparent'] = true;
|
||||
params['opacity'] = value;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'map_bump':
|
||||
case 'bump':
|
||||
|
||||
// Bump texture map
|
||||
|
||||
if ( params[ 'bumpMap' ] ) break; // Avoid loading twice.
|
||||
|
||||
params[ 'bumpMap' ] = this.loadTexture( this.baseUrl + value );
|
||||
params[ 'bumpMap' ].wrapS = this.wrap;
|
||||
params[ 'bumpMap' ].wrapT = this.wrap;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( params[ 'diffuse' ] ) {
|
||||
|
||||
params[ 'color' ] = params[ 'diffuse' ];
|
||||
|
||||
}
|
||||
|
||||
this.materials[ materialName ] = new THREE.MeshPhongMaterial( params );
|
||||
return this.materials[ materialName ];
|
||||
|
||||
},
|
||||
|
||||
|
||||
loadTexture: function ( url, mapping, onLoad, onError ) {
|
||||
|
||||
var texture;
|
||||
var loader = THREE.Loader.Handlers.get( url );
|
||||
|
||||
if ( loader !== null ) {
|
||||
|
||||
texture = loader.load( url, onLoad );
|
||||
|
||||
} else {
|
||||
|
||||
texture = new THREE.Texture();
|
||||
|
||||
loader = new THREE.ImageLoader();
|
||||
loader.crossOrigin = this.crossOrigin;
|
||||
loader.load( url, function ( image ) {
|
||||
|
||||
texture.image = THREE.MTLLoader.ensurePowerOfTwo_( image );
|
||||
texture.needsUpdate = true;
|
||||
|
||||
if ( onLoad ) onLoad( texture );
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
if ( mapping !== undefined ) texture.mapping = mapping;
|
||||
|
||||
return texture;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
THREE.MTLLoader.ensurePowerOfTwo_ = function ( image ) {
|
||||
|
||||
if ( ! THREE.Math.isPowerOfTwo( image.width ) || ! THREE.Math.isPowerOfTwo( image.height ) ) {
|
||||
|
||||
var canvas = document.createElement( "canvas" );
|
||||
canvas.width = THREE.MTLLoader.nextHighestPowerOfTwo_( image.width );
|
||||
canvas.height = THREE.MTLLoader.nextHighestPowerOfTwo_( image.height );
|
||||
|
||||
var ctx = canvas.getContext("2d");
|
||||
ctx.drawImage( image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height );
|
||||
return canvas;
|
||||
|
||||
}
|
||||
|
||||
return image;
|
||||
|
||||
};
|
||||
|
||||
THREE.MTLLoader.nextHighestPowerOfTwo_ = function( x ) {
|
||||
|
||||
-- x;
|
||||
|
||||
for ( var i = 1; i < 32; i <<= 1 ) {
|
||||
|
||||
x = x | x >> i;
|
||||
|
||||
}
|
||||
|
||||
return x + 1;
|
||||
|
||||
};
|
||||
|
||||
THREE.EventDispatcher.prototype.apply( THREE.MTLLoader.prototype );
|
||||
372
js/three/OBJLoader.js
Normal file
372
js/three/OBJLoader.js
Normal file
@@ -0,0 +1,372 @@
|
||||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
THREE.OBJLoader = function ( manager ) {
|
||||
|
||||
this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
|
||||
|
||||
};
|
||||
|
||||
THREE.OBJLoader.prototype = {
|
||||
|
||||
constructor: THREE.OBJLoader,
|
||||
|
||||
load: function ( url, onLoad, onProgress, onError ) {
|
||||
|
||||
var scope = this;
|
||||
|
||||
var loader = new THREE.XHRLoader( scope.manager );
|
||||
loader.setCrossOrigin( this.crossOrigin );
|
||||
loader.load( url, function ( text ) {
|
||||
|
||||
onLoad( scope.parse( text ) );
|
||||
|
||||
}, onProgress, onError );
|
||||
|
||||
},
|
||||
|
||||
parse: function ( text ) {
|
||||
|
||||
console.time( 'OBJLoader' );
|
||||
|
||||
var object, objects = [];
|
||||
var geometry, material;
|
||||
|
||||
function parseVertexIndex( value ) {
|
||||
|
||||
var index = parseInt( value );
|
||||
|
||||
return ( index >= 0 ? index - 1 : index + vertices.length / 3 ) * 3;
|
||||
|
||||
}
|
||||
|
||||
function parseNormalIndex( value ) {
|
||||
|
||||
var index = parseInt( value );
|
||||
|
||||
return ( index >= 0 ? index - 1 : index + normals.length / 3 ) * 3;
|
||||
|
||||
}
|
||||
|
||||
function parseUVIndex( value ) {
|
||||
|
||||
var index = parseInt( value );
|
||||
|
||||
return ( index >= 0 ? index - 1 : index + uvs.length / 2 ) * 2;
|
||||
|
||||
}
|
||||
|
||||
function addVertex( a, b, c ) {
|
||||
|
||||
geometry.vertices.push(
|
||||
vertices[ a ], vertices[ a + 1 ], vertices[ a + 2 ],
|
||||
vertices[ b ], vertices[ b + 1 ], vertices[ b + 2 ],
|
||||
vertices[ c ], vertices[ c + 1 ], vertices[ c + 2 ]
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
function addNormal( a, b, c ) {
|
||||
|
||||
geometry.normals.push(
|
||||
normals[ a ], normals[ a + 1 ], normals[ a + 2 ],
|
||||
normals[ b ], normals[ b + 1 ], normals[ b + 2 ],
|
||||
normals[ c ], normals[ c + 1 ], normals[ c + 2 ]
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
function addUV( a, b, c ) {
|
||||
|
||||
geometry.uvs.push(
|
||||
uvs[ a ], uvs[ a + 1 ],
|
||||
uvs[ b ], uvs[ b + 1 ],
|
||||
uvs[ c ], uvs[ c + 1 ]
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
function addFace( a, b, c, d, ua, ub, uc, ud, na, nb, nc, nd ) {
|
||||
|
||||
var ia = parseVertexIndex( a );
|
||||
var ib = parseVertexIndex( b );
|
||||
var ic = parseVertexIndex( c );
|
||||
var id;
|
||||
|
||||
if ( d === undefined ) {
|
||||
|
||||
addVertex( ia, ib, ic );
|
||||
|
||||
} else {
|
||||
|
||||
id = parseVertexIndex( d );
|
||||
|
||||
addVertex( ia, ib, id );
|
||||
addVertex( ib, ic, id );
|
||||
|
||||
}
|
||||
|
||||
if ( ua !== undefined ) {
|
||||
|
||||
ia = parseUVIndex( ua );
|
||||
ib = parseUVIndex( ub );
|
||||
ic = parseUVIndex( uc );
|
||||
|
||||
if ( d === undefined ) {
|
||||
|
||||
addUV( ia, ib, ic );
|
||||
|
||||
} else {
|
||||
|
||||
id = parseUVIndex( ud );
|
||||
|
||||
addUV( ia, ib, id );
|
||||
addUV( ib, ic, id );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( na !== undefined ) {
|
||||
|
||||
ia = parseNormalIndex( na );
|
||||
ib = parseNormalIndex( nb );
|
||||
ic = parseNormalIndex( nc );
|
||||
|
||||
if ( d === undefined ) {
|
||||
|
||||
addNormal( ia, ib, ic );
|
||||
|
||||
} else {
|
||||
|
||||
id = parseNormalIndex( nd );
|
||||
|
||||
addNormal( ia, ib, id );
|
||||
addNormal( ib, ic, id );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// create mesh if no objects in text
|
||||
|
||||
if ( /^o /gm.test( text ) === false ) {
|
||||
|
||||
geometry = {
|
||||
vertices: [],
|
||||
normals: [],
|
||||
uvs: []
|
||||
};
|
||||
|
||||
material = {
|
||||
name: ''
|
||||
};
|
||||
|
||||
object = {
|
||||
name: '',
|
||||
geometry: geometry,
|
||||
material: material
|
||||
};
|
||||
|
||||
objects.push( object );
|
||||
|
||||
}
|
||||
|
||||
var vertices = [];
|
||||
var normals = [];
|
||||
var uvs = [];
|
||||
|
||||
// v float float float
|
||||
|
||||
var vertex_pattern = /v( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/;
|
||||
|
||||
// vn float float float
|
||||
|
||||
var normal_pattern = /vn( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/;
|
||||
|
||||
// vt float float
|
||||
|
||||
var uv_pattern = /vt( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/;
|
||||
|
||||
// f vertex vertex vertex ...
|
||||
|
||||
var face_pattern1 = /f( +-?\d+)( +-?\d+)( +-?\d+)( +-?\d+)?/;
|
||||
|
||||
// f vertex/uv vertex/uv vertex/uv ...
|
||||
|
||||
var face_pattern2 = /f( +(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+))?/;
|
||||
|
||||
// f vertex/uv/normal vertex/uv/normal vertex/uv/normal ...
|
||||
|
||||
var face_pattern3 = /f( +(-?\d+)\/(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+)\/(-?\d+))?/;
|
||||
|
||||
// f vertex//normal vertex//normal vertex//normal ...
|
||||
|
||||
var face_pattern4 = /f( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))?/
|
||||
|
||||
//
|
||||
|
||||
var lines = text.split( '\n' );
|
||||
|
||||
for ( var i = 0; i < lines.length; i ++ ) {
|
||||
|
||||
var line = lines[ i ];
|
||||
line = line.trim();
|
||||
|
||||
var result;
|
||||
|
||||
if ( line.length === 0 || line.charAt( 0 ) === '#' ) {
|
||||
|
||||
continue;
|
||||
|
||||
} else if ( ( result = vertex_pattern.exec( line ) ) !== null ) {
|
||||
|
||||
// ["v 1.0 2.0 3.0", "1.0", "2.0", "3.0"]
|
||||
|
||||
vertices.push(
|
||||
parseFloat( result[ 1 ] ),
|
||||
parseFloat( result[ 2 ] ),
|
||||
parseFloat( result[ 3 ] )
|
||||
);
|
||||
|
||||
} else if ( ( result = normal_pattern.exec( line ) ) !== null ) {
|
||||
|
||||
// ["vn 1.0 2.0 3.0", "1.0", "2.0", "3.0"]
|
||||
|
||||
normals.push(
|
||||
parseFloat( result[ 1 ] ),
|
||||
parseFloat( result[ 2 ] ),
|
||||
parseFloat( result[ 3 ] )
|
||||
);
|
||||
|
||||
} else if ( ( result = uv_pattern.exec( line ) ) !== null ) {
|
||||
|
||||
// ["vt 0.1 0.2", "0.1", "0.2"]
|
||||
|
||||
uvs.push(
|
||||
parseFloat( result[ 1 ] ),
|
||||
parseFloat( result[ 2 ] )
|
||||
);
|
||||
|
||||
} else if ( ( result = face_pattern1.exec( line ) ) !== null ) {
|
||||
|
||||
// ["f 1 2 3", "1", "2", "3", undefined]
|
||||
|
||||
addFace(
|
||||
result[ 1 ], result[ 2 ], result[ 3 ], result[ 4 ]
|
||||
);
|
||||
|
||||
} else if ( ( result = face_pattern2.exec( line ) ) !== null ) {
|
||||
|
||||
// ["f 1/1 2/2 3/3", " 1/1", "1", "1", " 2/2", "2", "2", " 3/3", "3", "3", undefined, undefined, undefined]
|
||||
|
||||
addFace(
|
||||
result[ 2 ], result[ 5 ], result[ 8 ], result[ 11 ],
|
||||
result[ 3 ], result[ 6 ], result[ 9 ], result[ 12 ]
|
||||
);
|
||||
|
||||
} else if ( ( result = face_pattern3.exec( line ) ) !== null ) {
|
||||
|
||||
// ["f 1/1/1 2/2/2 3/3/3", " 1/1/1", "1", "1", "1", " 2/2/2", "2", "2", "2", " 3/3/3", "3", "3", "3", undefined, undefined, undefined, undefined]
|
||||
|
||||
addFace(
|
||||
result[ 2 ], result[ 6 ], result[ 10 ], result[ 14 ],
|
||||
result[ 3 ], result[ 7 ], result[ 11 ], result[ 15 ],
|
||||
result[ 4 ], result[ 8 ], result[ 12 ], result[ 16 ]
|
||||
);
|
||||
|
||||
} else if ( ( result = face_pattern4.exec( line ) ) !== null ) {
|
||||
|
||||
// ["f 1//1 2//2 3//3", " 1//1", "1", "1", " 2//2", "2", "2", " 3//3", "3", "3", undefined, undefined, undefined]
|
||||
|
||||
addFace(
|
||||
result[ 2 ], result[ 5 ], result[ 8 ], result[ 11 ],
|
||||
undefined, undefined, undefined, undefined,
|
||||
result[ 3 ], result[ 6 ], result[ 9 ], result[ 12 ]
|
||||
);
|
||||
|
||||
} else if ( /^o /.test( line ) ) {
|
||||
|
||||
geometry = {
|
||||
vertices: [],
|
||||
normals: [],
|
||||
uvs: []
|
||||
};
|
||||
|
||||
material = {
|
||||
name: ''
|
||||
};
|
||||
|
||||
object = {
|
||||
name: line.substring( 2 ).trim(),
|
||||
geometry: geometry,
|
||||
material: material
|
||||
};
|
||||
|
||||
objects.push( object )
|
||||
|
||||
} else if ( /^g /.test( line ) ) {
|
||||
|
||||
// group
|
||||
|
||||
} else if ( /^usemtl /.test( line ) ) {
|
||||
|
||||
// material
|
||||
|
||||
material.name = line.substring( 7 ).trim();
|
||||
|
||||
} else if ( /^mtllib /.test( line ) ) {
|
||||
|
||||
// mtl file
|
||||
|
||||
} else if ( /^s /.test( line ) ) {
|
||||
|
||||
// smooth shading
|
||||
|
||||
} else {
|
||||
|
||||
// console.log( "THREE.OBJLoader: Unhandled line " + line );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var container = new THREE.Object3D();
|
||||
|
||||
for ( var i = 0, l = objects.length; i < l; i ++ ) {
|
||||
|
||||
object = objects[ i ];
|
||||
geometry = object.geometry;
|
||||
|
||||
var buffergeometry = new THREE.BufferGeometry();
|
||||
|
||||
buffergeometry.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( geometry.vertices ), 3 ) );
|
||||
|
||||
if ( geometry.normals.length > 0 ) {
|
||||
buffergeometry.addAttribute( 'normal', new THREE.BufferAttribute( new Float32Array( geometry.normals ), 3 ) );
|
||||
}
|
||||
|
||||
if ( geometry.uvs.length > 0 ) {
|
||||
buffergeometry.addAttribute( 'uv', new THREE.BufferAttribute( new Float32Array( geometry.uvs ), 2 ) );
|
||||
}
|
||||
|
||||
material = new THREE.MeshLambertMaterial();
|
||||
material.name = object.material.name;
|
||||
|
||||
var mesh = new THREE.Mesh( buffergeometry, material );
|
||||
mesh.name = object.name;
|
||||
|
||||
container.add( mesh );
|
||||
|
||||
}
|
||||
|
||||
console.timeEnd( 'OBJLoader' );
|
||||
|
||||
return container;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
365
js/three/OBJMTLLoader.js
Normal file
365
js/three/OBJMTLLoader.js
Normal file
@@ -0,0 +1,365 @@
|
||||
/**
|
||||
* Loads a Wavefront .obj file with materials
|
||||
*
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author angelxuanchang
|
||||
*/
|
||||
|
||||
THREE.OBJMTLLoader = function ( manager ) {
|
||||
|
||||
this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
|
||||
|
||||
};
|
||||
|
||||
THREE.OBJMTLLoader.prototype = {
|
||||
|
||||
constructor: THREE.OBJMTLLoader,
|
||||
|
||||
load: function ( url, mtlurl, onLoad, onProgress, onError ) {
|
||||
|
||||
var scope = this;
|
||||
|
||||
var mtlLoader = new THREE.MTLLoader( url.substr( 0, url.lastIndexOf( "/" ) + 1 ) );
|
||||
mtlLoader.crossOrigin = scope.crossOrigin;
|
||||
mtlLoader.load( mtlurl, function ( materials ) {
|
||||
|
||||
var materialsCreator = materials;
|
||||
materialsCreator.preload();
|
||||
|
||||
var loader = new THREE.XHRLoader( scope.manager );
|
||||
loader.setCrossOrigin( scope.crossOrigin );
|
||||
loader.load( url, function ( text ) {
|
||||
|
||||
var object = scope.parse( text );
|
||||
|
||||
object.traverse( function ( object ) {
|
||||
|
||||
if ( object instanceof THREE.Mesh ) {
|
||||
|
||||
if ( object.material.name ) {
|
||||
|
||||
var material = materialsCreator.create( object.material.name );
|
||||
|
||||
if ( material ) object.material = material;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
onLoad( object );
|
||||
|
||||
}, onProgress, onError );
|
||||
|
||||
}, onProgress, onError );
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Parses loaded .obj file
|
||||
* @param data - content of .obj file
|
||||
* @param mtllibCallback - callback to handle mtllib declaration (optional)
|
||||
* @return {THREE.Object3D} - Object3D (with default material)
|
||||
*/
|
||||
|
||||
parse: function ( data, mtllibCallback ) {
|
||||
|
||||
function vector( x, y, z ) {
|
||||
|
||||
return new THREE.Vector3( x, y, z );
|
||||
|
||||
}
|
||||
|
||||
function uv( u, v ) {
|
||||
|
||||
return new THREE.Vector2( u, v );
|
||||
|
||||
}
|
||||
|
||||
function face3( a, b, c, normals ) {
|
||||
|
||||
return new THREE.Face3( a, b, c, normals );
|
||||
|
||||
}
|
||||
|
||||
var face_offset = 0;
|
||||
|
||||
function meshN( meshName, materialName ) {
|
||||
|
||||
if ( vertices.length > 0 ) {
|
||||
|
||||
geometry.vertices = vertices;
|
||||
|
||||
geometry.mergeVertices();
|
||||
geometry.computeFaceNormals();
|
||||
geometry.computeBoundingSphere();
|
||||
|
||||
object.add( mesh );
|
||||
|
||||
geometry = new THREE.Geometry();
|
||||
mesh = new THREE.Mesh( geometry, material );
|
||||
|
||||
}
|
||||
|
||||
if ( meshName !== undefined ) mesh.name = meshName;
|
||||
|
||||
if ( materialName !== undefined ) {
|
||||
|
||||
material = new THREE.MeshLambertMaterial();
|
||||
material.name = materialName;
|
||||
|
||||
mesh.material = material;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var group = new THREE.Group();
|
||||
var object = group;
|
||||
|
||||
var geometry = new THREE.Geometry();
|
||||
var material = new THREE.MeshLambertMaterial();
|
||||
var mesh = new THREE.Mesh( geometry, material );
|
||||
|
||||
var vertices = [];
|
||||
var normals = [];
|
||||
var uvs = [];
|
||||
|
||||
function add_face( a, b, c, normals_inds ) {
|
||||
|
||||
if ( normals_inds === undefined ) {
|
||||
|
||||
geometry.faces.push( face3(
|
||||
parseInt( a ) - (face_offset + 1),
|
||||
parseInt( b ) - (face_offset + 1),
|
||||
parseInt( c ) - (face_offset + 1)
|
||||
) );
|
||||
|
||||
} else {
|
||||
|
||||
geometry.faces.push( face3(
|
||||
parseInt( a ) - (face_offset + 1),
|
||||
parseInt( b ) - (face_offset + 1),
|
||||
parseInt( c ) - (face_offset + 1),
|
||||
[
|
||||
normals[ parseInt( normals_inds[ 0 ] ) - 1 ].clone(),
|
||||
normals[ parseInt( normals_inds[ 1 ] ) - 1 ].clone(),
|
||||
normals[ parseInt( normals_inds[ 2 ] ) - 1 ].clone()
|
||||
]
|
||||
) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function add_uvs( a, b, c ) {
|
||||
|
||||
geometry.faceVertexUvs[ 0 ].push( [
|
||||
uvs[ parseInt( a ) - 1 ].clone(),
|
||||
uvs[ parseInt( b ) - 1 ].clone(),
|
||||
uvs[ parseInt( c ) - 1 ].clone()
|
||||
] );
|
||||
|
||||
}
|
||||
|
||||
function handle_face_line(faces, uvs, normals_inds) {
|
||||
|
||||
if ( faces[ 3 ] === undefined ) {
|
||||
|
||||
add_face( faces[ 0 ], faces[ 1 ], faces[ 2 ], normals_inds );
|
||||
|
||||
if (!(uvs === undefined) && uvs.length > 0) {
|
||||
add_uvs( uvs[ 0 ], uvs[ 1 ], uvs[ 2 ] );
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (!(normals_inds === undefined) && normals_inds.length > 0) {
|
||||
|
||||
add_face( faces[ 0 ], faces[ 1 ], faces[ 3 ], [ normals_inds[ 0 ], normals_inds[ 1 ], normals_inds[ 3 ] ]);
|
||||
add_face( faces[ 1 ], faces[ 2 ], faces[ 3 ], [ normals_inds[ 1 ], normals_inds[ 2 ], normals_inds[ 3 ] ]);
|
||||
|
||||
} else {
|
||||
|
||||
add_face( faces[ 0 ], faces[ 1 ], faces[ 3 ]);
|
||||
add_face( faces[ 1 ], faces[ 2 ], faces[ 3 ]);
|
||||
|
||||
}
|
||||
|
||||
if (!(uvs === undefined) && uvs.length > 0) {
|
||||
|
||||
add_uvs( uvs[ 0 ], uvs[ 1 ], uvs[ 3 ] );
|
||||
add_uvs( uvs[ 1 ], uvs[ 2 ], uvs[ 3 ] );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// v float float float
|
||||
|
||||
var vertex_pattern = /v( +[\d|\.|\+|\-|e]+)( +[\d|\.|\+|\-|e]+)( +[\d|\.|\+|\-|e]+)/;
|
||||
|
||||
// vn float float float
|
||||
|
||||
var normal_pattern = /vn( +[\d|\.|\+|\-|e]+)( +[\d|\.|\+|\-|e]+)( +[\d|\.|\+|\-|e]+)/;
|
||||
|
||||
// vt float float
|
||||
|
||||
var uv_pattern = /vt( +[\d|\.|\+|\-|e]+)( +[\d|\.|\+|\-|e]+)/;
|
||||
|
||||
// f vertex vertex vertex ...
|
||||
|
||||
var face_pattern1 = /f( +\d+)( +\d+)( +\d+)( +\d+)?/;
|
||||
|
||||
// f vertex/uv vertex/uv vertex/uv ...
|
||||
|
||||
var face_pattern2 = /f( +(\d+)\/(\d+))( +(\d+)\/(\d+))( +(\d+)\/(\d+))( +(\d+)\/(\d+))?/;
|
||||
|
||||
// f vertex/uv/normal vertex/uv/normal vertex/uv/normal ...
|
||||
|
||||
var face_pattern3 = /f( +(\d+)\/(\d+)\/(\d+))( +(\d+)\/(\d+)\/(\d+))( +(\d+)\/(\d+)\/(\d+))( +(\d+)\/(\d+)\/(\d+))?/;
|
||||
|
||||
// f vertex//normal vertex//normal vertex//normal ...
|
||||
|
||||
var face_pattern4 = /f( +(\d+)\/\/(\d+))( +(\d+)\/\/(\d+))( +(\d+)\/\/(\d+))( +(\d+)\/\/(\d+))?/
|
||||
|
||||
//
|
||||
|
||||
var lines = data.split( "\n" );
|
||||
|
||||
for ( var i = 0; i < lines.length; i ++ ) {
|
||||
|
||||
var line = lines[ i ];
|
||||
line = line.trim();
|
||||
|
||||
var result;
|
||||
|
||||
if ( line.length === 0 || line.charAt( 0 ) === '#' ) {
|
||||
|
||||
continue;
|
||||
|
||||
} else if ( ( result = vertex_pattern.exec( line ) ) !== null ) {
|
||||
|
||||
// ["v 1.0 2.0 3.0", "1.0", "2.0", "3.0"]
|
||||
|
||||
vertices.push( vector(
|
||||
parseFloat( result[ 1 ] ),
|
||||
parseFloat( result[ 2 ] ),
|
||||
parseFloat( result[ 3 ] )
|
||||
) );
|
||||
|
||||
} else if ( ( result = normal_pattern.exec( line ) ) !== null ) {
|
||||
|
||||
// ["vn 1.0 2.0 3.0", "1.0", "2.0", "3.0"]
|
||||
|
||||
normals.push( vector(
|
||||
parseFloat( result[ 1 ] ),
|
||||
parseFloat( result[ 2 ] ),
|
||||
parseFloat( result[ 3 ] )
|
||||
) );
|
||||
|
||||
} else if ( ( result = uv_pattern.exec( line ) ) !== null ) {
|
||||
|
||||
// ["vt 0.1 0.2", "0.1", "0.2"]
|
||||
|
||||
uvs.push( uv(
|
||||
parseFloat( result[ 1 ] ),
|
||||
parseFloat( result[ 2 ] )
|
||||
) );
|
||||
|
||||
} else if ( ( result = face_pattern1.exec( line ) ) !== null ) {
|
||||
|
||||
// ["f 1 2 3", "1", "2", "3", undefined]
|
||||
|
||||
handle_face_line([ result[ 1 ], result[ 2 ], result[ 3 ], result[ 4 ] ]);
|
||||
|
||||
} else if ( ( result = face_pattern2.exec( line ) ) !== null ) {
|
||||
|
||||
// ["f 1/1 2/2 3/3", " 1/1", "1", "1", " 2/2", "2", "2", " 3/3", "3", "3", undefined, undefined, undefined]
|
||||
|
||||
handle_face_line(
|
||||
[ result[ 2 ], result[ 5 ], result[ 8 ], result[ 11 ] ], //faces
|
||||
[ result[ 3 ], result[ 6 ], result[ 9 ], result[ 12 ] ] //uv
|
||||
);
|
||||
|
||||
} else if ( ( result = face_pattern3.exec( line ) ) !== null ) {
|
||||
|
||||
// ["f 1/1/1 2/2/2 3/3/3", " 1/1/1", "1", "1", "1", " 2/2/2", "2", "2", "2", " 3/3/3", "3", "3", "3", undefined, undefined, undefined, undefined]
|
||||
|
||||
handle_face_line(
|
||||
[ result[ 2 ], result[ 6 ], result[ 10 ], result[ 14 ] ], //faces
|
||||
[ result[ 3 ], result[ 7 ], result[ 11 ], result[ 15 ] ], //uv
|
||||
[ result[ 4 ], result[ 8 ], result[ 12 ], result[ 16 ] ] //normal
|
||||
);
|
||||
|
||||
} else if ( ( result = face_pattern4.exec( line ) ) !== null ) {
|
||||
|
||||
// ["f 1//1 2//2 3//3", " 1//1", "1", "1", " 2//2", "2", "2", " 3//3", "3", "3", undefined, undefined, undefined]
|
||||
|
||||
handle_face_line(
|
||||
[ result[ 2 ], result[ 5 ], result[ 8 ], result[ 11 ] ], //faces
|
||||
[ ], //uv
|
||||
[ result[ 3 ], result[ 6 ], result[ 9 ], result[ 12 ] ] //normal
|
||||
);
|
||||
|
||||
} else if ( /^o /.test( line ) ) {
|
||||
|
||||
// object
|
||||
|
||||
meshN();
|
||||
face_offset = face_offset + vertices.length;
|
||||
vertices = [];
|
||||
object = new THREE.Object3D();
|
||||
object.name = line.substring( 2 ).trim();
|
||||
group.add( object );
|
||||
|
||||
} else if ( /^g /.test( line ) ) {
|
||||
|
||||
// group
|
||||
|
||||
meshN( line.substring( 2 ).trim(), undefined );
|
||||
|
||||
} else if ( /^usemtl /.test( line ) ) {
|
||||
|
||||
// material
|
||||
|
||||
meshN( undefined, line.substring( 7 ).trim() );
|
||||
|
||||
} else if ( /^mtllib /.test( line ) ) {
|
||||
|
||||
// mtl file
|
||||
|
||||
if ( mtllibCallback ) {
|
||||
|
||||
var mtlfile = line.substring( 7 );
|
||||
mtlfile = mtlfile.trim();
|
||||
mtllibCallback( mtlfile );
|
||||
|
||||
}
|
||||
|
||||
} else if ( /^s /.test( line ) ) {
|
||||
|
||||
// Smooth shading
|
||||
|
||||
} else {
|
||||
|
||||
console.log( "THREE.OBJMTLLoader: Unhandled line " + line );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Add last object
|
||||
meshN(undefined, undefined);
|
||||
|
||||
return group;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
THREE.EventDispatcher.prototype.apply( THREE.OBJMTLLoader.prototype );
|
||||
706
js/three/OrbitControls.js
Normal file
706
js/three/OrbitControls.js
Normal file
@@ -0,0 +1,706 @@
|
||||
/**
|
||||
* @author qiao / https://github.com/qiao
|
||||
* @author mrdoob / http://mrdoob.com
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
* @author WestLangley / http://github.com/WestLangley
|
||||
* @author erich666 / http://erichaines.com
|
||||
*/
|
||||
/*global THREE, console */
|
||||
|
||||
// This set of controls performs orbiting, dollying (zooming), and panning. It maintains
|
||||
// the "up" direction as +Y, unlike the TrackballControls. Touch on tablet and phones is
|
||||
// supported.
|
||||
//
|
||||
// Orbit - left mouse / touch: one finger move
|
||||
// Zoom - middle mouse, or mousewheel / touch: two finger spread or squish
|
||||
// Pan - right mouse, or arrow keys / touch: three finter swipe
|
||||
|
||||
THREE.OrbitControls = function ( object, domElement ) {
|
||||
|
||||
this.object = object;
|
||||
this.domElement = ( domElement !== undefined ) ? domElement : document;
|
||||
|
||||
// API
|
||||
|
||||
// Set to false to disable this control
|
||||
this.enabled = true;
|
||||
|
||||
// "target" sets the location of focus, where the control orbits around
|
||||
// and where it pans with respect to.
|
||||
this.target = new THREE.Vector3();
|
||||
|
||||
// center is old, deprecated; use "target" instead
|
||||
this.center = this.target;
|
||||
|
||||
// This option actually enables dollying in and out; left as "zoom" for
|
||||
// backwards compatibility
|
||||
this.noZoom = false;
|
||||
this.zoomSpeed = 1.0;
|
||||
|
||||
// Limits to how far you can dolly in and out ( PerspectiveCamera only )
|
||||
this.minDistance = 0;
|
||||
this.maxDistance = Infinity;
|
||||
|
||||
// Limits to how far you can zoom in and out ( OrthographicCamera only )
|
||||
this.minZoom = 0;
|
||||
this.maxZoom = Infinity;
|
||||
|
||||
// Set to true to disable this control
|
||||
this.noRotate = false;
|
||||
this.rotateSpeed = 1.0;
|
||||
|
||||
// Set to true to disable this control
|
||||
this.noPan = false;
|
||||
this.keyPanSpeed = 7.0; // pixels moved per arrow key push
|
||||
|
||||
// Set to true to automatically rotate around the target
|
||||
this.autoRotate = false;
|
||||
this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60
|
||||
|
||||
// How far you can orbit vertically, upper and lower limits.
|
||||
// Range is 0 to Math.PI radians.
|
||||
this.minPolarAngle = 0; // radians
|
||||
this.maxPolarAngle = Math.PI; // radians
|
||||
|
||||
// How far you can orbit horizontally, upper and lower limits.
|
||||
// If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].
|
||||
this.minAzimuthAngle = - Infinity; // radians
|
||||
this.maxAzimuthAngle = Infinity; // radians
|
||||
|
||||
// Set to true to disable use of the keys
|
||||
this.noKeys = false;
|
||||
|
||||
// The four arrow keys
|
||||
this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };
|
||||
|
||||
// Mouse buttons
|
||||
this.mouseButtons = { ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT };
|
||||
|
||||
////////////
|
||||
// internals
|
||||
|
||||
var scope = this;
|
||||
|
||||
var EPS = 0.000001;
|
||||
|
||||
var rotateStart = new THREE.Vector2();
|
||||
var rotateEnd = new THREE.Vector2();
|
||||
var rotateDelta = new THREE.Vector2();
|
||||
|
||||
var panStart = new THREE.Vector2();
|
||||
var panEnd = new THREE.Vector2();
|
||||
var panDelta = new THREE.Vector2();
|
||||
var panOffset = new THREE.Vector3();
|
||||
|
||||
var offset = new THREE.Vector3();
|
||||
|
||||
var dollyStart = new THREE.Vector2();
|
||||
var dollyEnd = new THREE.Vector2();
|
||||
var dollyDelta = new THREE.Vector2();
|
||||
|
||||
var theta;
|
||||
var phi;
|
||||
var phiDelta = 0;
|
||||
var thetaDelta = 0;
|
||||
var scale = 1;
|
||||
var pan = new THREE.Vector3();
|
||||
|
||||
var lastPosition = new THREE.Vector3();
|
||||
var lastQuaternion = new THREE.Quaternion();
|
||||
|
||||
var STATE = { NONE : -1, ROTATE : 0, DOLLY : 1, PAN : 2, TOUCH_ROTATE : 3, TOUCH_DOLLY : 4, TOUCH_PAN : 5 };
|
||||
|
||||
var state = STATE.NONE;
|
||||
|
||||
// for reset
|
||||
|
||||
this.target0 = this.target.clone();
|
||||
this.position0 = this.object.position.clone();
|
||||
this.zoom0 = this.object.zoom;
|
||||
|
||||
// so camera.up is the orbit axis
|
||||
|
||||
var quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) );
|
||||
var quatInverse = quat.clone().inverse();
|
||||
|
||||
// events
|
||||
|
||||
var changeEvent = { type: 'change' };
|
||||
var startEvent = { type: 'start' };
|
||||
var endEvent = { type: 'end' };
|
||||
|
||||
this.rotateLeft = function ( angle ) {
|
||||
|
||||
if ( angle === undefined ) {
|
||||
|
||||
angle = getAutoRotationAngle();
|
||||
|
||||
}
|
||||
|
||||
thetaDelta -= angle;
|
||||
|
||||
};
|
||||
|
||||
this.rotateUp = function ( angle ) {
|
||||
|
||||
if ( angle === undefined ) {
|
||||
|
||||
angle = getAutoRotationAngle();
|
||||
|
||||
}
|
||||
|
||||
phiDelta -= angle;
|
||||
|
||||
};
|
||||
|
||||
// pass in distance in world space to move left
|
||||
this.panLeft = function ( distance ) {
|
||||
|
||||
var te = this.object.matrix.elements;
|
||||
|
||||
// get X column of matrix
|
||||
panOffset.set( te[ 0 ], te[ 1 ], te[ 2 ] );
|
||||
panOffset.multiplyScalar( - distance );
|
||||
|
||||
pan.add( panOffset );
|
||||
|
||||
};
|
||||
|
||||
// pass in distance in world space to move up
|
||||
this.panUp = function ( distance ) {
|
||||
|
||||
var te = this.object.matrix.elements;
|
||||
|
||||
// get Y column of matrix
|
||||
panOffset.set( te[ 4 ], te[ 5 ], te[ 6 ] );
|
||||
panOffset.multiplyScalar( distance );
|
||||
|
||||
pan.add( panOffset );
|
||||
|
||||
};
|
||||
|
||||
// pass in x,y of change desired in pixel space,
|
||||
// right and down are positive
|
||||
this.pan = function ( deltaX, deltaY ) {
|
||||
|
||||
var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
|
||||
|
||||
if ( scope.object instanceof THREE.PerspectiveCamera ) {
|
||||
|
||||
// perspective
|
||||
var position = scope.object.position;
|
||||
var offset = position.clone().sub( scope.target );
|
||||
var targetDistance = offset.length();
|
||||
|
||||
// half of the fov is center to top of screen
|
||||
targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 );
|
||||
|
||||
// we actually don't use screenWidth, since perspective camera is fixed to screen height
|
||||
scope.panLeft( 2 * deltaX * targetDistance / element.clientHeight );
|
||||
scope.panUp( 2 * deltaY * targetDistance / element.clientHeight );
|
||||
|
||||
} else if ( scope.object instanceof THREE.OrthographicCamera ) {
|
||||
|
||||
// orthographic
|
||||
scope.panLeft( deltaX * (scope.object.right - scope.object.left) / element.clientWidth );
|
||||
scope.panUp( deltaY * (scope.object.top - scope.object.bottom) / element.clientHeight );
|
||||
|
||||
} else {
|
||||
|
||||
// camera neither orthographic or perspective
|
||||
console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
this.dollyIn = function ( dollyScale ) {
|
||||
|
||||
if ( dollyScale === undefined ) {
|
||||
|
||||
dollyScale = getZoomScale();
|
||||
|
||||
}
|
||||
|
||||
if ( scope.object instanceof THREE.PerspectiveCamera ) {
|
||||
|
||||
scale /= dollyScale;
|
||||
|
||||
} else if ( scope.object instanceof THREE.OrthographicCamera ) {
|
||||
|
||||
scope.object.zoom = Math.max( this.minZoom, Math.min( this.maxZoom, this.object.zoom * dollyScale ) );
|
||||
scope.object.updateProjectionMatrix();
|
||||
scope.dispatchEvent( changeEvent );
|
||||
|
||||
} else {
|
||||
|
||||
console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
this.dollyOut = function ( dollyScale ) {
|
||||
|
||||
if ( dollyScale === undefined ) {
|
||||
|
||||
dollyScale = getZoomScale();
|
||||
|
||||
}
|
||||
|
||||
if ( scope.object instanceof THREE.PerspectiveCamera ) {
|
||||
|
||||
scale *= dollyScale;
|
||||
|
||||
} else if ( scope.object instanceof THREE.OrthographicCamera ) {
|
||||
|
||||
scope.object.zoom = Math.max( this.minZoom, Math.min( this.maxZoom, this.object.zoom / dollyScale ) );
|
||||
scope.object.updateProjectionMatrix();
|
||||
scope.dispatchEvent( changeEvent );
|
||||
|
||||
} else {
|
||||
|
||||
console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
this.update = function () {
|
||||
|
||||
var position = this.object.position;
|
||||
|
||||
offset.copy( position ).sub( this.target );
|
||||
|
||||
// rotate offset to "y-axis-is-up" space
|
||||
offset.applyQuaternion( quat );
|
||||
|
||||
// angle from z-axis around y-axis
|
||||
|
||||
theta = Math.atan2( offset.x, offset.z );
|
||||
|
||||
// angle from y-axis
|
||||
|
||||
phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y );
|
||||
|
||||
if ( this.autoRotate && state === STATE.NONE ) {
|
||||
|
||||
this.rotateLeft( getAutoRotationAngle() );
|
||||
|
||||
}
|
||||
|
||||
theta += thetaDelta;
|
||||
phi += phiDelta;
|
||||
|
||||
// restrict theta to be between desired limits
|
||||
theta = Math.max( this.minAzimuthAngle, Math.min( this.maxAzimuthAngle, theta ) );
|
||||
|
||||
// restrict phi to be between desired limits
|
||||
phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) );
|
||||
|
||||
// restrict phi to be betwee EPS and PI-EPS
|
||||
phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) );
|
||||
|
||||
var radius = offset.length() * scale;
|
||||
|
||||
// restrict radius to be between desired limits
|
||||
radius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) );
|
||||
|
||||
// move target to panned location
|
||||
this.target.add( pan );
|
||||
|
||||
offset.x = radius * Math.sin( phi ) * Math.sin( theta );
|
||||
offset.y = radius * Math.cos( phi );
|
||||
offset.z = radius * Math.sin( phi ) * Math.cos( theta );
|
||||
|
||||
// rotate offset back to "camera-up-vector-is-up" space
|
||||
offset.applyQuaternion( quatInverse );
|
||||
|
||||
position.copy( this.target ).add( offset );
|
||||
|
||||
this.object.lookAt( this.target );
|
||||
|
||||
thetaDelta = 0;
|
||||
phiDelta = 0;
|
||||
scale = 1;
|
||||
pan.set( 0, 0, 0 );
|
||||
|
||||
// update condition is:
|
||||
// min(camera displacement, camera rotation in radians)^2 > EPS
|
||||
// using small-angle approximation cos(x/2) = 1 - x^2 / 8
|
||||
|
||||
if ( lastPosition.distanceToSquared( this.object.position ) > EPS
|
||||
|| 8 * (1 - lastQuaternion.dot(this.object.quaternion)) > EPS ) {
|
||||
|
||||
this.dispatchEvent( changeEvent );
|
||||
|
||||
lastPosition.copy( this.object.position );
|
||||
lastQuaternion.copy (this.object.quaternion );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
this.reset = function () {
|
||||
|
||||
state = STATE.NONE;
|
||||
|
||||
this.target.copy( this.target0 );
|
||||
this.object.position.copy( this.position0 );
|
||||
this.object.zoom = this.zoom0;
|
||||
|
||||
this.object.updateProjectionMatrix();
|
||||
this.dispatchEvent( changeEvent );
|
||||
|
||||
this.update();
|
||||
|
||||
};
|
||||
|
||||
this.getPolarAngle = function () {
|
||||
|
||||
return phi;
|
||||
|
||||
};
|
||||
|
||||
this.getAzimuthalAngle = function () {
|
||||
|
||||
return theta
|
||||
|
||||
};
|
||||
|
||||
function getAutoRotationAngle() {
|
||||
|
||||
return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
|
||||
|
||||
}
|
||||
|
||||
function getZoomScale() {
|
||||
|
||||
return Math.pow( 0.95, scope.zoomSpeed );
|
||||
|
||||
}
|
||||
|
||||
function onMouseDown( event ) {
|
||||
|
||||
if ( scope.enabled === false ) return;
|
||||
event.preventDefault();
|
||||
|
||||
if ( event.button === scope.mouseButtons.ORBIT ) {
|
||||
if ( scope.noRotate === true ) return;
|
||||
|
||||
state = STATE.ROTATE;
|
||||
|
||||
rotateStart.set( event.clientX, event.clientY );
|
||||
|
||||
} else if ( event.button === scope.mouseButtons.ZOOM ) {
|
||||
if ( scope.noZoom === true ) return;
|
||||
|
||||
state = STATE.DOLLY;
|
||||
|
||||
dollyStart.set( event.clientX, event.clientY );
|
||||
|
||||
} else if ( event.button === scope.mouseButtons.PAN ) {
|
||||
if ( scope.noPan === true ) return;
|
||||
|
||||
state = STATE.PAN;
|
||||
|
||||
panStart.set( event.clientX, event.clientY );
|
||||
|
||||
}
|
||||
|
||||
if ( state !== STATE.NONE ) {
|
||||
document.addEventListener( 'mousemove', onMouseMove, false );
|
||||
document.addEventListener( 'mouseup', onMouseUp, false );
|
||||
scope.dispatchEvent( startEvent );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function onMouseMove( event ) {
|
||||
|
||||
if ( scope.enabled === false ) return;
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
|
||||
|
||||
if ( state === STATE.ROTATE ) {
|
||||
|
||||
if ( scope.noRotate === true ) return;
|
||||
|
||||
rotateEnd.set( event.clientX, event.clientY );
|
||||
rotateDelta.subVectors( rotateEnd, rotateStart );
|
||||
|
||||
// rotating across whole screen goes 360 degrees around
|
||||
scope.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed );
|
||||
|
||||
// rotating up and down along whole screen attempts to go 360, but limited to 180
|
||||
scope.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed );
|
||||
|
||||
rotateStart.copy( rotateEnd );
|
||||
|
||||
} else if ( state === STATE.DOLLY ) {
|
||||
|
||||
if ( scope.noZoom === true ) return;
|
||||
|
||||
dollyEnd.set( event.clientX, event.clientY );
|
||||
dollyDelta.subVectors( dollyEnd, dollyStart );
|
||||
|
||||
if ( dollyDelta.y > 0 ) {
|
||||
|
||||
scope.dollyIn();
|
||||
|
||||
} else if ( dollyDelta.y < 0 ) {
|
||||
|
||||
scope.dollyOut();
|
||||
|
||||
}
|
||||
|
||||
dollyStart.copy( dollyEnd );
|
||||
|
||||
} else if ( state === STATE.PAN ) {
|
||||
|
||||
if ( scope.noPan === true ) return;
|
||||
|
||||
panEnd.set( event.clientX, event.clientY );
|
||||
panDelta.subVectors( panEnd, panStart );
|
||||
|
||||
scope.pan( panDelta.x, panDelta.y );
|
||||
|
||||
panStart.copy( panEnd );
|
||||
|
||||
}
|
||||
|
||||
if ( state !== STATE.NONE ) scope.update();
|
||||
|
||||
}
|
||||
|
||||
function onMouseUp( /* event */ ) {
|
||||
|
||||
if ( scope.enabled === false ) return;
|
||||
|
||||
document.removeEventListener( 'mousemove', onMouseMove, false );
|
||||
document.removeEventListener( 'mouseup', onMouseUp, false );
|
||||
scope.dispatchEvent( endEvent );
|
||||
state = STATE.NONE;
|
||||
|
||||
}
|
||||
|
||||
function onMouseWheel( event ) {
|
||||
|
||||
if ( scope.enabled === false || scope.noZoom === true || state !== STATE.NONE ) return;
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
var delta = 0;
|
||||
|
||||
if ( event.wheelDelta !== undefined ) { // WebKit / Opera / Explorer 9
|
||||
|
||||
delta = event.wheelDelta;
|
||||
|
||||
} else if ( event.detail !== undefined ) { // Firefox
|
||||
|
||||
delta = - event.detail;
|
||||
|
||||
}
|
||||
|
||||
if ( delta > 0 ) {
|
||||
|
||||
scope.dollyOut();
|
||||
|
||||
} else if ( delta < 0 ) {
|
||||
|
||||
scope.dollyIn();
|
||||
|
||||
}
|
||||
|
||||
scope.update();
|
||||
scope.dispatchEvent( startEvent );
|
||||
scope.dispatchEvent( endEvent );
|
||||
|
||||
}
|
||||
|
||||
function onKeyDown( event ) {
|
||||
|
||||
if ( scope.enabled === false || scope.noKeys === true || scope.noPan === true ) return;
|
||||
|
||||
switch ( event.keyCode ) {
|
||||
|
||||
case scope.keys.UP:
|
||||
scope.pan( 0, scope.keyPanSpeed );
|
||||
scope.update();
|
||||
break;
|
||||
|
||||
case scope.keys.BOTTOM:
|
||||
scope.pan( 0, - scope.keyPanSpeed );
|
||||
scope.update();
|
||||
break;
|
||||
|
||||
case scope.keys.LEFT:
|
||||
scope.pan( scope.keyPanSpeed, 0 );
|
||||
scope.update();
|
||||
break;
|
||||
|
||||
case scope.keys.RIGHT:
|
||||
scope.pan( - scope.keyPanSpeed, 0 );
|
||||
scope.update();
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function touchstart( event ) {
|
||||
|
||||
if ( scope.enabled === false ) return;
|
||||
|
||||
switch ( event.touches.length ) {
|
||||
|
||||
case 1: // one-fingered touch: rotate
|
||||
|
||||
if ( scope.noRotate === true ) return;
|
||||
|
||||
state = STATE.TOUCH_ROTATE;
|
||||
|
||||
rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
|
||||
break;
|
||||
|
||||
case 2: // two-fingered touch: dolly
|
||||
|
||||
if ( scope.noZoom === true ) return;
|
||||
|
||||
state = STATE.TOUCH_DOLLY;
|
||||
|
||||
var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
|
||||
var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
|
||||
var distance = Math.sqrt( dx * dx + dy * dy );
|
||||
dollyStart.set( 0, distance );
|
||||
break;
|
||||
|
||||
case 3: // three-fingered touch: pan
|
||||
|
||||
if ( scope.noPan === true ) return;
|
||||
|
||||
state = STATE.TOUCH_PAN;
|
||||
|
||||
panStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
state = STATE.NONE;
|
||||
|
||||
}
|
||||
|
||||
if ( state !== STATE.NONE ) scope.dispatchEvent( startEvent );
|
||||
|
||||
}
|
||||
|
||||
function touchmove( event ) {
|
||||
|
||||
if ( scope.enabled === false ) return;
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
|
||||
|
||||
switch ( event.touches.length ) {
|
||||
|
||||
case 1: // one-fingered touch: rotate
|
||||
|
||||
if ( scope.noRotate === true ) return;
|
||||
if ( state !== STATE.TOUCH_ROTATE ) return;
|
||||
|
||||
rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
|
||||
rotateDelta.subVectors( rotateEnd, rotateStart );
|
||||
|
||||
// rotating across whole screen goes 360 degrees around
|
||||
scope.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed );
|
||||
// rotating up and down along whole screen attempts to go 360, but limited to 180
|
||||
scope.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed );
|
||||
|
||||
rotateStart.copy( rotateEnd );
|
||||
|
||||
scope.update();
|
||||
break;
|
||||
|
||||
case 2: // two-fingered touch: dolly
|
||||
|
||||
if ( scope.noZoom === true ) return;
|
||||
if ( state !== STATE.TOUCH_DOLLY ) return;
|
||||
|
||||
var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
|
||||
var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
|
||||
var distance = Math.sqrt( dx * dx + dy * dy );
|
||||
|
||||
dollyEnd.set( 0, distance );
|
||||
dollyDelta.subVectors( dollyEnd, dollyStart );
|
||||
|
||||
if ( dollyDelta.y > 0 ) {
|
||||
|
||||
scope.dollyOut();
|
||||
|
||||
} else if ( dollyDelta.y < 0 ) {
|
||||
|
||||
scope.dollyIn();
|
||||
|
||||
}
|
||||
|
||||
dollyStart.copy( dollyEnd );
|
||||
|
||||
scope.update();
|
||||
break;
|
||||
|
||||
case 3: // three-fingered touch: pan
|
||||
|
||||
if ( scope.noPan === true ) return;
|
||||
if ( state !== STATE.TOUCH_PAN ) return;
|
||||
|
||||
panEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
|
||||
panDelta.subVectors( panEnd, panStart );
|
||||
|
||||
scope.pan( panDelta.x, panDelta.y );
|
||||
|
||||
panStart.copy( panEnd );
|
||||
|
||||
scope.update();
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
state = STATE.NONE;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function touchend( /* event */ ) {
|
||||
|
||||
if ( scope.enabled === false ) return;
|
||||
|
||||
scope.dispatchEvent( endEvent );
|
||||
state = STATE.NONE;
|
||||
|
||||
}
|
||||
|
||||
this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
|
||||
this.domElement.addEventListener( 'mousedown', onMouseDown, false );
|
||||
this.domElement.addEventListener( 'mousewheel', onMouseWheel, false );
|
||||
this.domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox
|
||||
|
||||
this.domElement.addEventListener( 'touchstart', touchstart, false );
|
||||
this.domElement.addEventListener( 'touchend', touchend, false );
|
||||
this.domElement.addEventListener( 'touchmove', touchmove, false );
|
||||
|
||||
window.addEventListener( 'keydown', onKeyDown, false );
|
||||
|
||||
// force an update at start
|
||||
this.update();
|
||||
|
||||
};
|
||||
|
||||
THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );
|
||||
THREE.OrbitControls.prototype.constructor = THREE.OrbitControls;
|
||||
6
js/three/stats.min.js
vendored
Normal file
6
js/three/stats.min.js
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
// stats.js - http://github.com/mrdoob/stats.js
|
||||
var Stats=function(){var l=Date.now(),m=l,g=0,n=Infinity,o=0,h=0,p=Infinity,q=0,r=0,s=0,f=document.createElement("div");f.id="stats";f.addEventListener("mousedown",function(b){b.preventDefault();t(++s%2)},!1);f.style.cssText="width:80px;opacity:0.9;cursor:pointer";var a=document.createElement("div");a.id="fps";a.style.cssText="padding:0 0 3px 3px;text-align:left;background-color:#002";f.appendChild(a);var i=document.createElement("div");i.id="fpsText";i.style.cssText="color:#0ff;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px";
|
||||
i.innerHTML="FPS";a.appendChild(i);var c=document.createElement("div");c.id="fpsGraph";c.style.cssText="position:relative;width:74px;height:30px;background-color:#0ff";for(a.appendChild(c);74>c.children.length;){var j=document.createElement("span");j.style.cssText="width:1px;height:30px;float:left;background-color:#113";c.appendChild(j)}var d=document.createElement("div");d.id="ms";d.style.cssText="padding:0 0 3px 3px;text-align:left;background-color:#020;display:none";f.appendChild(d);var k=document.createElement("div");
|
||||
k.id="msText";k.style.cssText="color:#0f0;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px";k.innerHTML="MS";d.appendChild(k);var e=document.createElement("div");e.id="msGraph";e.style.cssText="position:relative;width:74px;height:30px;background-color:#0f0";for(d.appendChild(e);74>e.children.length;)j=document.createElement("span"),j.style.cssText="width:1px;height:30px;float:left;background-color:#131",e.appendChild(j);var t=function(b){s=b;switch(s){case 0:a.style.display=
|
||||
"block";d.style.display="none";break;case 1:a.style.display="none",d.style.display="block"}};return{REVISION:12,domElement:f,setMode:t,begin:function(){l=Date.now()},end:function(){var b=Date.now();g=b-l;n=Math.min(n,g);o=Math.max(o,g);k.textContent=g+" MS ("+n+"-"+o+")";var a=Math.min(30,30-30*(g/200));e.appendChild(e.firstChild).style.height=a+"px";r++;b>m+1E3&&(h=Math.round(1E3*r/(b-m)),p=Math.min(p,h),q=Math.max(q,h),i.textContent=h+" FPS ("+p+"-"+q+")",a=Math.min(30,30-30*(h/100)),c.appendChild(c.firstChild).style.height=
|
||||
a+"px",m=b,r=0);return b},update:function(){l=this.end()}}};"object"===typeof module&&(module.exports=Stats);
|
||||
835
js/three/three.min.js
vendored
Normal file
835
js/three/three.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user