From python CGI to jekyll stuff
This commit is contained in:
@@ -1,36 +0,0 @@
|
||||
DT = new THREE.Vector3(0.1,0.1,0.1);
|
||||
FRICTION = new THREE.Vector3(1, 1, 1);
|
||||
G = new THREE.Vector3(0,0,-10);
|
||||
|
||||
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(DT);
|
||||
|
||||
this.speed.add(G);
|
||||
|
||||
if (this.speed.dot(this.speed) > 100) {
|
||||
this.center.add(speed_clone);
|
||||
}
|
||||
|
||||
if (this.center.z < 0) {
|
||||
this.speed.multiply(new THREE.Vector3(1,1,-0.5));
|
||||
this.center.z = 0;
|
||||
}
|
||||
|
||||
// Update the mesh
|
||||
this.mesh.position.set(this.center.x, this.center.y, this.center.z);
|
||||
|
||||
// console.log(this.center.x, this.center.y, this.center.z);
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
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
28
js/Camera.js
@@ -1,28 +0,0 @@
|
||||
// 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;
|
||||
@@ -1,70 +0,0 @@
|
||||
var CameraContainer = function () {
|
||||
this.cameras = new Array();
|
||||
}
|
||||
|
||||
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) {
|
||||
this.cameras.forEach(callback);
|
||||
}
|
||||
|
||||
CameraContainer.prototype.look = function() {
|
||||
this.mainCamera().look();
|
||||
}
|
||||
|
||||
CameraContainer.prototype.updateMainCamera = function() {
|
||||
this.pointerCamera.update();
|
||||
}
|
||||
|
||||
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.getById = function(id) {
|
||||
for (var i in this.cameras) {
|
||||
if (this.cameras[i].object3D !== undefined) {
|
||||
if (this.cameras[i].object3D.id == id) {
|
||||
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
50
js/Cube.js
@@ -1,50 +0,0 @@
|
||||
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);
|
||||
}
|
||||
@@ -1,231 +0,0 @@
|
||||
// Initialization
|
||||
|
||||
// class camera extends THREE.PerspectiveCamera
|
||||
var FixedCamera = 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,20));
|
||||
// this.up = new THREE.Vector3(0,0,1);
|
||||
|
||||
// Compute corners
|
||||
|
||||
// Create the mesh to draw
|
||||
|
||||
var geometry = new THREE.Geometry();
|
||||
|
||||
this.center = this.position.clone();
|
||||
var left = Tools.cross(direction, this.up);
|
||||
var other = Tools.cross(direction, left);
|
||||
|
||||
this.center.sub(direction);
|
||||
|
||||
left.normalize();
|
||||
other.normalize();
|
||||
left = Tools.mul(left, 0.2);
|
||||
other = Tools.mul(other, 0.2);
|
||||
|
||||
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,1,2), // new THREE.Face3(0,2,1),
|
||||
new THREE.Face3(0,2,3), // 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();
|
||||
|
||||
(function(self, direction, left, other, position) {
|
||||
var material = new THREE.LineBasicMaterial({ color: '0x000000', transparent: true});
|
||||
var geometry = new THREE.Geometry();
|
||||
// var direction = Tools.mul(direction, 1);
|
||||
var target = Tools.sum(position, direction);
|
||||
// geometry.vertices.push(position, target);
|
||||
geometry.vertices.push(
|
||||
Tools.sum(Tools.sum(position, left), other),
|
||||
Tools.diff(Tools.sum(position, other),left),
|
||||
Tools.diff(Tools.diff(position, left),other),
|
||||
Tools.sum(Tools.diff(position, other), left),
|
||||
Tools.sum(Tools.sum(position, left), other),
|
||||
Tools.sum(Tools.diff(position, other), left),
|
||||
|
||||
Tools.sum(position, direction),
|
||||
Tools.sum(Tools.sum(position, left), other),
|
||||
|
||||
Tools.sum(position, direction),
|
||||
Tools.diff(Tools.sum(position, other),left),
|
||||
|
||||
Tools.sum(position, direction),
|
||||
Tools.diff(Tools.diff(position, left),other),
|
||||
|
||||
Tools.sum(position, direction),
|
||||
Tools.sum(Tools.diff(position, other), left)
|
||||
);
|
||||
|
||||
self.border = new THREE.Line(geometry, material);
|
||||
})(this, direction, left, other, position);
|
||||
|
||||
|
||||
var material = new THREE.MeshLambertMaterial({
|
||||
color : 0xff0000,
|
||||
transparent : true,
|
||||
opacity : 0.5,
|
||||
side: THREE.DoubleSide
|
||||
});
|
||||
|
||||
this.mesh = new THREE.Mesh(geometry, material);
|
||||
// this.arrow = new THREE.Line(new THREE.Geometry(), new THREE.LineBasicMaterial({color: 0xff0000}), THREE.LinePieces);
|
||||
this.arrow = new THREE.Mesh(new THREE.Geometry(), new THREE.MeshLambertMaterial({color: 0xff0000, side:THREE.DoubleSide}));
|
||||
|
||||
this.object3D = new THREE.Object3D();
|
||||
this.object3D.add(this.mesh);
|
||||
this.object3D.add(this.arrow);
|
||||
|
||||
this.fullArrow = false;
|
||||
}
|
||||
FixedCamera.prototype = Object.create(THREE.PerspectiveCamera.prototype);
|
||||
FixedCamera.prototype.constructor = FixedCamera;
|
||||
|
||||
// Update function
|
||||
FixedCamera.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);
|
||||
}
|
||||
|
||||
FixedCamera.prototype.regenerateArrow = function(mainCamera) {
|
||||
var vertices = new Array();
|
||||
var t = [0,1];
|
||||
var f0 = mainCamera.position.clone();
|
||||
f0.add(Tools.sum(Tools.mul(this.up,-1), Tools.diff(this.target, this.position).normalize()));
|
||||
var f = [Tools.sum(mainCamera.position, Tools.diff(this.target, this.position)).normalize(), this.position.clone()];
|
||||
|
||||
var first = Tools.diff(mainCamera.target, mainCamera.position);
|
||||
first.normalize();
|
||||
|
||||
var fp = [Tools.mul(first,40), Tools.diff(this.target, this.position)];
|
||||
fp[1].normalize();
|
||||
fp[1].multiplyScalar(4);
|
||||
var hermite = new Hermite.special.Polynom(f0, f[1], fp[1]);
|
||||
|
||||
var up = this.up.clone();
|
||||
var point;
|
||||
var deriv;
|
||||
var limit = this.fullArrow ? 0.1 : 0.2;
|
||||
|
||||
// for (var i = this.fullArrow ? 0 : 0.5; i <= 1.001; i += 0.05) {
|
||||
for (var i = 1; i > limit; i -= 0.01) {
|
||||
point = hermite.eval(i);
|
||||
deriv = hermite.prime(i);
|
||||
up.cross(deriv);
|
||||
up.cross(deriv);
|
||||
up.multiplyScalar(-1);
|
||||
up.normalize();
|
||||
|
||||
var coeff = 0.1;
|
||||
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)
|
||||
);
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
|
||||
this.arrow.geometry.vertices = vertices;
|
||||
this.arrow.geometry.faces = faces;
|
||||
|
||||
// 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;
|
||||
this.arrow.geometry.facesNeedUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
// Look function
|
||||
FixedCamera.prototype.look = function() {
|
||||
this.lookAt(this.target);
|
||||
}
|
||||
|
||||
FixedCamera.prototype.addToScene = function(scene) {
|
||||
scene.add(this);
|
||||
scene.add(this.object3D);
|
||||
}
|
||||
|
||||
FixedCamera.prototype.traverse = function(callback) {
|
||||
this.object3D.traverse(callback);
|
||||
}
|
||||
201
js/Hermite.js
201
js/Hermite.js
@@ -1,201 +0,0 @@
|
||||
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);
|
||||
}
|
||||
@@ -1,276 +0,0 @@
|
||||
// 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.up = new THREE.Vector3(0,0,1);
|
||||
this.target = new THREE.Vector3(0,1,0);
|
||||
|
||||
// Stuff for events
|
||||
this.moveForward = false;
|
||||
this.moveBackward = false;
|
||||
this.moveRight = false;
|
||||
this.moveLeft = false;
|
||||
|
||||
this.sensitivity = 0.05;
|
||||
this.speed = 1;
|
||||
|
||||
// Raycaster for collisions
|
||||
this.raycaster = new THREE.Raycaster();
|
||||
|
||||
// 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('mouseout', onMouseUp, false);
|
||||
|
||||
this.collisions = true;
|
||||
}
|
||||
PointerCamera.prototype = Object.create(THREE.PerspectiveCamera.prototype);
|
||||
PointerCamera.prototype.constructor = PointerCamera;
|
||||
|
||||
// Update function
|
||||
PointerCamera.prototype.update = function() {
|
||||
if (this.moving) {
|
||||
// Linear version
|
||||
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));
|
||||
this.target.add(Tools.mul(target_direction, 0.05));
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
// Hermite polynom version
|
||||
// var eval = this.hermite.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.hermite.prime(this.t));
|
||||
|
||||
// this.t += 0.005;
|
||||
|
||||
// if (this.t > 1) {
|
||||
// this.moving = false;
|
||||
// // 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);
|
||||
|
||||
// }
|
||||
|
||||
} else {
|
||||
// Update angles
|
||||
if (this.increasePhi) this.phi += this.sensitivity;
|
||||
if (this.decreasePhi) this.phi -= this.sensitivity;
|
||||
if (this.increaseTheta) this.theta += this.sensitivity;
|
||||
if (this.decreaseTheta) this.theta -= this.sensitivity;
|
||||
|
||||
if (this.dragging) {
|
||||
this.theta += this.mouseMove.x;
|
||||
this.phi -= this.mouseMove.y;
|
||||
|
||||
this.mouseMove.x = 0;
|
||||
this.mouseMove.y = 0;
|
||||
}
|
||||
|
||||
// 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;
|
||||
var direction = new THREE.Vector3();
|
||||
|
||||
if (this.boost) speed *= 10;
|
||||
if (this.moveForward) direction.add(Tools.mul(forward, speed));
|
||||
if (this.moveBackward) direction.sub(Tools.mul(forward, speed));
|
||||
if (this.moveLeft) direction.add(Tools.mul(left, speed));
|
||||
if (this.moveRight) direction.sub(Tools.mul(left, speed));
|
||||
|
||||
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.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.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() {
|
||||
// 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);
|
||||
}
|
||||
|
||||
PointerCamera.prototype.move = function(otherCamera) {
|
||||
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;
|
||||
}
|
||||
|
||||
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 < 0.1) {
|
||||
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) {
|
||||
switch ( event.keyCode ) {
|
||||
// Azerty keyboards
|
||||
case 38: case 90: this.moveForward = toSet; break; // up / z
|
||||
case 37: case 81: this.moveLeft = toSet; break; // left / q
|
||||
case 40: case 83: this.moveBackward = toSet; break; // down / s
|
||||
case 39: case 68: this.moveRight = toSet; break; // right / d
|
||||
case 32: this.boost = toSet; break;
|
||||
|
||||
// Qwerty keyboards
|
||||
// case 38: case 87: this.moveForward = toSet; break; // up / w
|
||||
// case 37: case 65: this.moveLeft = toSet; break; // left / a
|
||||
// case 40: case 83: this.moveBackward = toSet; break; // down / s
|
||||
// case 39: case 68: this.moveRight = toSet; break; // right / d
|
||||
|
||||
case 73: case 104: this.increasePhi = toSet; break; // 8 Up for angle
|
||||
case 75: case 98: this.decreasePhi = toSet; break; // 2 Down for angle
|
||||
case 74: case 100: this.increaseTheta = toSet; break; // 4 Left for angle
|
||||
case 76: case 102: this.decreaseTheta = toSet; break; // 6 Right for angle
|
||||
|
||||
case 13: if (toSet) this.log(); break;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
PointerCamera.prototype.onMouseUp = function(event) {
|
||||
this.onMouseMove(event);
|
||||
this.dragging = false;
|
||||
}
|
||||
|
||||
PointerCamera.prototype.log = function() {
|
||||
console.log("(" + this.position.x + "," + this.position.y + ',' + this.position.z + ')');
|
||||
console.log("(" + this.target.x + "," + this.target.y + ',' + this.target.z + ')');
|
||||
}
|
||||
|
||||
// Static members
|
||||
PointerCamera.DISTANCE_X = 1000;
|
||||
PointerCamera.DISTANCE_Z = 300;
|
||||
@@ -1,89 +0,0 @@
|
||||
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;
|
||||
}
|
||||
41
js/Tools.js
41
js/Tools.js
@@ -1,41 +0,0 @@
|
||||
var Tools = {version : "1.0" };
|
||||
|
||||
Tools.sum = function(v1, v2) {
|
||||
var ret = v1.clone();
|
||||
ret.add(v2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Tools.diff = function(v1, v2) {
|
||||
var ret = v1.clone();
|
||||
ret.sub(v2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Tools.dot = function(v1, v2) {
|
||||
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
|
||||
}
|
||||
|
||||
Tools.cross = function(v1, v2) {
|
||||
var ret = v1.clone();
|
||||
ret.cross(v2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Tools.mul = function(v1, lambda) {
|
||||
var ret = v1.clone();
|
||||
ret.multiplyScalar(lambda);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
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();
|
||||
35133
js/three.js
35133
js/three.js
File diff suppressed because one or more lines are too long
@@ -1,237 +0,0 @@
|
||||
/*
|
||||
* @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;
|
||||
|
||||
};
|
||||
|
||||
@@ -1,441 +0,0 @@
|
||||
/**
|
||||
* 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 );
|
||||
@@ -1,372 +0,0 @@
|
||||
/**
|
||||
* @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;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
@@ -1,365 +0,0 @@
|
||||
/**
|
||||
* 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 );
|
||||
@@ -1,706 +0,0 @@
|
||||
/**
|
||||
* @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
6
js/three/stats.min.js
vendored
@@ -1,6 +0,0 @@
|
||||
// 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
835
js/three/three.min.js
vendored
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user