A hell of a lot cleaning
This commit is contained in:
31
js/l3d/src/cameras/Camera.js
Normal file
31
js/l3d/src/cameras/Camera.js
Normal file
@@ -0,0 +1,31 @@
|
||||
// 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(time) {
|
||||
if (time === undefined) {
|
||||
time = 20;
|
||||
}
|
||||
this.theta += 0.01 * time / 20;
|
||||
this.position.x = Camera.DISTANCE_X*Math.cos(this.theta);
|
||||
this.position.y = Camera.DISTANCE_X*Math.sin(this.theta);
|
||||
};
|
||||
|
||||
// Look function
|
||||
Camera.prototype.look = function() {
|
||||
this.lookAt(this.target);
|
||||
};
|
||||
|
||||
// Static members
|
||||
Camera.DISTANCE_X = 1000;
|
||||
Camera.DISTANCE_Z = 300;
|
||||
77
js/l3d/src/cameras/CameraContainer.js
Normal file
77
js/l3d/src/cameras/CameraContainer.js
Normal file
@@ -0,0 +1,77 @@
|
||||
var CameraContainer = function (pointerCamera, cameras) {
|
||||
if (cameras !== undefined) {
|
||||
this.cameras = cameras;
|
||||
} else {
|
||||
this.cameras = [];
|
||||
}
|
||||
|
||||
if (pointerCamera !== undefined) {
|
||||
this.push(pointerCamera);
|
||||
}
|
||||
};
|
||||
|
||||
CameraContainer.prototype.mainCamera = function(id) {
|
||||
if (id === undefined) {
|
||||
return this.pointerCamera;
|
||||
}
|
||||
if (id >= cameras.length || id < 0) {
|
||||
console.log('Warning : this camera does not exist');
|
||||
return;
|
||||
}
|
||||
|
||||
this.current_camera = id;
|
||||
};
|
||||
|
||||
CameraContainer.prototype.forEach = function(callback) {
|
||||
callback(this.pointerCamera);
|
||||
this.cameras.forEach(callback);
|
||||
};
|
||||
|
||||
CameraContainer.prototype.look = function() {
|
||||
this.mainCamera().look();
|
||||
};
|
||||
|
||||
CameraContainer.prototype.updateMainCamera = function(time) {
|
||||
this.pointerCamera.update(time);
|
||||
};
|
||||
|
||||
CameraContainer.prototype.update = function(position) {
|
||||
this.cameras.map(function (elt) { elt.update(position); });
|
||||
};
|
||||
|
||||
CameraContainer.prototype.push = function(camera) {
|
||||
this.pointerCamera = camera;
|
||||
this.push = function(camera) {
|
||||
this.cameras.push(camera);
|
||||
};
|
||||
};
|
||||
|
||||
CameraContainer.prototype.get = function(i) {
|
||||
return this.cameras[i];
|
||||
};
|
||||
|
||||
CameraContainer.prototype.getByObject = function(object) {
|
||||
for (var i in this.cameras) {
|
||||
if (this.cameras[i].containsObject(object)) {
|
||||
return this.get(i);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CameraContainer.prototype.setById = function(id) {
|
||||
var i = this.getById(id);
|
||||
|
||||
if (i !== -1)
|
||||
this.current_camera = i;
|
||||
};
|
||||
|
||||
CameraContainer.prototype.nextCamera = function() {
|
||||
if (this.cameras.length !== 0) {
|
||||
this.current_camera++;
|
||||
this.current_camera%=this.cameras.length;
|
||||
}
|
||||
};
|
||||
|
||||
CameraContainer.prototype.map = function(callback) {
|
||||
this.cameras.map(callback);
|
||||
};
|
||||
743
js/l3d/src/cameras/PointerCamera.js
Normal file
743
js/l3d/src/cameras/PointerCamera.js
Normal file
@@ -0,0 +1,743 @@
|
||||
/**
|
||||
* Represents a camera that can be used easily
|
||||
* @constructor
|
||||
* @augments THREE.PerspectiveCamera
|
||||
*/
|
||||
var PointerCamera = function() {
|
||||
THREE.PerspectiveCamera.apply(this, arguments);
|
||||
|
||||
/**
|
||||
* A reference to the renderer
|
||||
* @type {THREE.Renderer}
|
||||
*/
|
||||
this.renderer = arguments[4];
|
||||
|
||||
if (arguments[5] === undefined)
|
||||
listenerTarget = document;
|
||||
else
|
||||
listenerTarget = arguments[5];
|
||||
|
||||
/**
|
||||
* Theta angle of the camera
|
||||
* @type {Number}
|
||||
*/
|
||||
this.theta = Math.PI;
|
||||
|
||||
/**
|
||||
* Phi angle of the camera
|
||||
* @type {Number}
|
||||
*/
|
||||
this.phi = Math.PI;
|
||||
|
||||
/**
|
||||
* Indicates if the camera is following a linear motion
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.moving = false;
|
||||
|
||||
/**
|
||||
* Indicates if the user is dragging the camera
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.dragging = false;
|
||||
|
||||
/**
|
||||
* Current position of the cursor
|
||||
* @type {Object}
|
||||
*/
|
||||
this.mouse = {x: 0, y: 0};
|
||||
|
||||
/**
|
||||
* Current movement of the cursor
|
||||
* @type {Object}
|
||||
*/
|
||||
this.mouseMove = {x: 0, y: 0};
|
||||
|
||||
/**
|
||||
* Current position of the camera (optical center)
|
||||
* @type {THREE.Vector}
|
||||
*/
|
||||
this.position = new THREE.Vector3();
|
||||
|
||||
/**
|
||||
* Current direction of the camera
|
||||
* @type {THREE.Vector}
|
||||
*/
|
||||
this.forward = new THREE.Vector3();
|
||||
|
||||
/**
|
||||
* Vector pointing to the left of the camera
|
||||
* @type {THREE.Vector}
|
||||
*/
|
||||
this.left = new THREE.Vector3();
|
||||
|
||||
/**
|
||||
* Point that the camera is targeting
|
||||
* @type {THREE.Vector}
|
||||
*/
|
||||
this.target = new THREE.Vector3(0,1,0);
|
||||
|
||||
/**
|
||||
* Indicates the different motions that the camera should have according to the keyboard events
|
||||
* @type {Object}
|
||||
* @description Contains the following booleans
|
||||
* <ul>
|
||||
* <li>increasePhi</li>
|
||||
* <li>decreasePhi</li>
|
||||
* <li>increaseTheta</li>
|
||||
* <li>decreaseTheta</li>
|
||||
* <li>boost</li>
|
||||
* <li>moveForward</li>
|
||||
* <li>moveBackward</li>
|
||||
* <li>moveLeft</li>
|
||||
* <li>moveRight</li>
|
||||
* </ul>
|
||||
*/
|
||||
this.motion = {};
|
||||
|
||||
/**
|
||||
* Sentitivity of the mouse
|
||||
* @type {Number}
|
||||
*/
|
||||
this.sensitivity = 0.05;
|
||||
|
||||
/**
|
||||
* Speed of the camera
|
||||
* @type {Number}
|
||||
*/
|
||||
this.speed = 1;
|
||||
|
||||
/**
|
||||
* Raycaster used to compute collisions
|
||||
* @type {THREE.Raycaster}
|
||||
*/
|
||||
this.raycaster = new THREE.Raycaster();
|
||||
|
||||
/**
|
||||
* History of the moves of the camera
|
||||
* @type {History}
|
||||
*/
|
||||
this.history = new History();
|
||||
|
||||
/**
|
||||
* Option to enable or disable the pointer lock
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.shouldLock = true;
|
||||
|
||||
/**
|
||||
* Current state of the pointer (locked or not)
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.pointerLocked = false;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
this.listenerTarget = listenerTarget;
|
||||
|
||||
// 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) {if (event.which === 1) self.onMouseDown(event); };
|
||||
var onMouseUp = function(event) {if (event.which === 1) self.onMouseUp(event); };
|
||||
var onMouseMove = function(event) {self.onMouseMove(event); };
|
||||
|
||||
document.addEventListener('keydown', onKeyDown, false);
|
||||
document.addEventListener('keyup', onKeyUp, false);
|
||||
|
||||
document.addEventListener('pointerlockchange', function(event) { self.onPointerLockChange(event); }, false);
|
||||
document.addEventListener('mozpointerlockchange', function(event) { self.onPointerLockChange(event); }, false);
|
||||
document.addEventListener('webkitpointerlockchange', function(event) { self.onPointerLockChange(event); }, false);
|
||||
|
||||
document.addEventListener('mousemove', function(event) {self.onMouseMovePointer(event);}, false);
|
||||
|
||||
listenerTarget.addEventListener('mousedown', function() {self.lockPointer();}, false);
|
||||
listenerTarget.addEventListener('mousedown', onMouseDown, false);
|
||||
listenerTarget.addEventListener('mousemove', onMouseMove, false);
|
||||
listenerTarget.addEventListener('mouseup', onMouseUp, false);
|
||||
listenerTarget.addEventListener('mouseout', onMouseUp, false);
|
||||
|
||||
/**
|
||||
* Option to enable or disable the collisions
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.collisions = true;
|
||||
|
||||
/**
|
||||
* Is true when we should log the camera angles. It will be set to false
|
||||
* once is done, and reset to true after a certain period of time
|
||||
* @param {Boolean}
|
||||
*/
|
||||
this.shouldLogCameraAngles = true;
|
||||
|
||||
/**
|
||||
* The camera we will move to when we'll reset the camera
|
||||
* @param {Object}
|
||||
*/
|
||||
this.resetElements = resetBobombElements();
|
||||
};
|
||||
PointerCamera.prototype = Object.create(THREE.PerspectiveCamera.prototype);
|
||||
PointerCamera.prototype.constructor = PointerCamera;
|
||||
|
||||
/**
|
||||
* Locks the pointer inside the canvas, and displays a gun sight at the middle of the renderer
|
||||
* This method works only if the browser supports requestPointerLock
|
||||
*/
|
||||
PointerCamera.prototype.lockPointer = function() {
|
||||
|
||||
if (this.shouldLock) {
|
||||
this.renderer.domElement.requestPointerLock =
|
||||
this.renderer.domElement.requestPointerLock ||
|
||||
this.renderer.domElement.mozRequestPointerLock ||
|
||||
this.renderer.domElement.webkitRequestPointerLock;
|
||||
|
||||
if (this.renderer.domElement.requestPointerLock) {
|
||||
|
||||
this.renderer.domElement.requestPointerLock();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Check that the pointer is locked or not, and updated locked attribute
|
||||
* @returns true if the pointer is locked, false otherwise
|
||||
*/
|
||||
PointerCamera.prototype.isLocked = function() {
|
||||
var toto =
|
||||
document.pointerLockElement === this.renderer.domElement ||
|
||||
document.mozPointerLockElement === this.renderer.domElement ||
|
||||
document.webkitPointerLockElement === this.renderer.domElement;
|
||||
|
||||
return toto;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the camera when the pointer lock changes state
|
||||
*/
|
||||
PointerCamera.prototype.onPointerLockChange = function() {
|
||||
|
||||
if (this.isLocked()) {
|
||||
|
||||
// The pointer is locked : adapt the state of the camera
|
||||
this.pointerLocked = true;
|
||||
this.mousePointer.render();
|
||||
|
||||
this.mouse.x = this.renderer.domElement.width/2;
|
||||
this.mouse.y = this.renderer.domElement.height/2;
|
||||
|
||||
// Remove start canvas
|
||||
this.startCanvas.clear();
|
||||
|
||||
} else {
|
||||
|
||||
this.pointerLocked = false;
|
||||
this.mousePointer.clear();
|
||||
|
||||
this.theta = this.previousTheta;
|
||||
this.phi = this.previousPhi;
|
||||
|
||||
this.mouseMove.x = 0;
|
||||
this.mouseMove.y = 0;
|
||||
|
||||
// Draw start canvas only if should lock
|
||||
if (this.shouldLock)
|
||||
this.startCanvas.render();
|
||||
else
|
||||
this.startCanvas.clear();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the position of the camera
|
||||
* @param {Number} time number of milliseconds between the previous and the next frame
|
||||
*/
|
||||
PointerCamera.prototype.update = function(time) {
|
||||
if (this.moving) {
|
||||
this.linearMotion(time);
|
||||
} else if (this.movingHermite) {
|
||||
this.hermiteMotion(time);
|
||||
} else {
|
||||
this.normalMotion(time);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the camera according to its linear motion
|
||||
* @param {Number} time number of milliseconds between the previous and the next frame
|
||||
*/
|
||||
PointerCamera.prototype.linearMotion = function(time) {
|
||||
var position_direction = Tools.diff(this.new_position, this.position);
|
||||
var target_direction = Tools.diff(this.new_target, this.target);
|
||||
|
||||
this.position.add(Tools.mul(position_direction, 0.05 * time / 20));
|
||||
this.target.add(Tools.mul(target_direction, 0.05 * time / 20));
|
||||
|
||||
if (Tools.norm2(Tools.diff(this.position, this.new_position)) < 0.01 &&
|
||||
Tools.norm2(Tools.diff(this.target, this.new_target)) < 0.01) {
|
||||
this.moving = false;
|
||||
this.anglesFromVectors();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the camera according to its hermite motion
|
||||
* @param {Number} time number of milliseconds between the previous and the next frame
|
||||
*/
|
||||
PointerCamera.prototype.hermiteMotion = function(time) {
|
||||
var e = this.hermitePosition.eval(this.t);
|
||||
this.position.x = e.x;
|
||||
this.position.y = e.y;
|
||||
this.position.z = e.z;
|
||||
|
||||
this.target = Tools.sum(this.position, this.hermiteAngles.eval(this.t));
|
||||
|
||||
this.t += 0.01 * time / 20;
|
||||
|
||||
if (this.t > 1) {
|
||||
this.movingHermite = false;
|
||||
this.anglesFromVectors();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the camera according to the user's input
|
||||
* @param {Number} time number of milliseconds between the previous and the next frame
|
||||
*/
|
||||
PointerCamera.prototype.normalMotion = function(time) {
|
||||
|
||||
// Update angles
|
||||
if (this.motion.increasePhi) {this.phi += this.sensitivity * time / 20; this.changed = true; }
|
||||
if (this.motion.decreasePhi) {this.phi -= this.sensitivity * time / 20; this.changed = true; }
|
||||
if (this.motion.increaseTheta) {this.theta += this.sensitivity * time / 20; this.changed = true; }
|
||||
if (this.motion.decreaseTheta) {this.theta -= this.sensitivity * time / 20; this.changed = true; }
|
||||
|
||||
if ( this.isLocked() || this.dragging) {
|
||||
|
||||
this.theta += (this.mouseMove.x * 20 / time);
|
||||
this.phi -= (this.mouseMove.y * 20 / time);
|
||||
|
||||
this.mouseMove.x = 0;
|
||||
this.mouseMove.y = 0;
|
||||
|
||||
this.vectorsFromAngles();
|
||||
|
||||
this.changed = true;
|
||||
|
||||
if (this.shouldLogCameraAngles) {
|
||||
|
||||
this.shouldLogCameraAngles = false;
|
||||
|
||||
var self = this;
|
||||
setTimeout(function() {
|
||||
self.shouldLogCameraAngles = true;
|
||||
}, 100);
|
||||
|
||||
var event = new BD.Event.KeyboardEvent();
|
||||
event.camera = this;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Clamp phi and theta
|
||||
this.phi = Math.min(Math.max(-(Math.PI/2-0.1),this.phi), Math.PI/2-0.1);
|
||||
this.theta = ((this.theta - Math.PI) % (2*Math.PI)) + Math.PI;
|
||||
|
||||
// Compute vectors (position and target)
|
||||
this.vectorsFromAngles();
|
||||
|
||||
// Update with events
|
||||
var delta = 0.1;
|
||||
var forward = this.forward.clone();
|
||||
forward.multiplyScalar(400.0 * delta);
|
||||
var left = this.up.clone();
|
||||
left.cross(forward);
|
||||
left.normalize();
|
||||
left.multiplyScalar(400.0 * delta);
|
||||
|
||||
// Move only if no collisions
|
||||
var speed = this.speed * time / 20;
|
||||
var direction = new THREE.Vector3();
|
||||
|
||||
if (this.motion.boost) speed *= 10;
|
||||
if (this.motion.moveForward) {direction.add(Tools.mul(forward, speed)); this.changed = true;}
|
||||
if (this.motion.moveBackward) {direction.sub(Tools.mul(forward, speed)); this.changed = true;}
|
||||
if (this.motion.moveLeft) {direction.add(Tools.mul(left, speed)); this.changed = true;}
|
||||
if (this.motion.moveRight) {direction.sub(Tools.mul(left, speed)); this.changed = true;}
|
||||
|
||||
if (!this.collisions || !this.isColliding(direction)) {
|
||||
this.position.add(direction);
|
||||
}
|
||||
|
||||
// Update angle
|
||||
this.target = this.position.clone();
|
||||
this.target.add(forward);
|
||||
};
|
||||
|
||||
/**
|
||||
* Reset the camera to its resetElements, and finishes any motion
|
||||
*/
|
||||
PointerCamera.prototype.reset = function() {
|
||||
this.resetPosition();
|
||||
this.moving = false;
|
||||
this.movingHermite = false;
|
||||
(new BD.Event.ResetClicked()).send();
|
||||
};
|
||||
|
||||
/**
|
||||
* Reset the position of th camera
|
||||
*/
|
||||
PointerCamera.prototype.resetPosition = function() {
|
||||
this.position.copy(this.resetElements.position);
|
||||
this.target.copy(this.resetElements.target);
|
||||
this.anglesFromVectors();
|
||||
};
|
||||
|
||||
/**
|
||||
* Computes the vectors (forward, left, ...) according to theta and phi
|
||||
*/
|
||||
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();
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Computes theta and phi according to the vectors (forward, left, ...)
|
||||
*/
|
||||
PointerCamera.prototype.anglesFromVectors = function() {
|
||||
var forward = Tools.diff(this.target, this.position);
|
||||
forward.normalize();
|
||||
|
||||
this.phi = Math.asin(forward.y);
|
||||
|
||||
// Don't know why this line works... But thanks Thierry-san and
|
||||
// Bastien because it seems to work...
|
||||
this.theta = Math.atan2(forward.x, forward.z);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a linear motion to another camera
|
||||
* @param {Camera} camera Camera to move to
|
||||
* @param {Boolean} [toSave=true] true if you want to save the current state of the camera
|
||||
*/
|
||||
PointerCamera.prototype.move = function(otherCamera, toSave) {
|
||||
if (toSave === undefined)
|
||||
toSave = true;
|
||||
|
||||
this.moving = true;
|
||||
this.new_target = otherCamera.target.clone();
|
||||
this.new_position = otherCamera.position.clone();
|
||||
var t = [0,1];
|
||||
var f = [this.position.clone(), this.new_position];
|
||||
var fp = [Tools.diff(this.target, this.position), Tools.diff(this.new_target, this.new_position)];
|
||||
this.hermite = new Hermite.Polynom(t,f,fp);
|
||||
this.t = 0;
|
||||
|
||||
if (toSave) {
|
||||
if (this.changed) {
|
||||
this.save();
|
||||
this.changed = false;
|
||||
}
|
||||
this.history.addState({position: otherCamera.position.clone(), target: otherCamera.target.clone()});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a hermite motion to another camera
|
||||
* @param {Camera} camera Camera to move to
|
||||
* @param {Boolean} [toSave=true] true if you want to save the current state of the camera
|
||||
*/
|
||||
PointerCamera.prototype.moveHermite = function(otherCamera, toSave) {
|
||||
if (toSave === undefined)
|
||||
toSave = true;
|
||||
|
||||
this.movingHermite = true;
|
||||
this.t = 0;
|
||||
|
||||
this.hermitePosition = new Hermite.special.Polynom(
|
||||
this.position.clone(),
|
||||
otherCamera.position.clone(),
|
||||
Tools.mul(Tools.diff(otherCamera.target, otherCamera.position).normalize(),4)
|
||||
);
|
||||
|
||||
this.hermiteAngles = new Hermite.special.Polynom(
|
||||
Tools.diff(this.target, this.position),
|
||||
Tools.diff(otherCamera.target, otherCamera.position),
|
||||
new THREE.Vector3()
|
||||
);
|
||||
|
||||
if (toSave) {
|
||||
if (this.changed) {
|
||||
this.save();
|
||||
this.changed = false;
|
||||
}
|
||||
this.history.addState({position: otherCamera.position.clone(), target: otherCamera.target.clone()});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks the collisions between the collidables objects and the camera
|
||||
* @param {THREE.Vector3} direction the direction of the camera
|
||||
* @returns {Boolean} true if there is a collision, false otherwise
|
||||
*/
|
||||
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 < Tools.norm(direction) + this.speed * 300 &&
|
||||
intersects[i].object.raycastable) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Look method. Equivalent to gluLookAt for the current camera
|
||||
*/
|
||||
PointerCamera.prototype.look = function() {
|
||||
this.lookAt(this.target);
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds the camera to the scene
|
||||
*/
|
||||
PointerCamera.prototype.addToScene = function(scene) {
|
||||
scene.add(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Manages keyboard events
|
||||
* @param {event} event the event that happened
|
||||
* @param {Booelean} toSet true if the key was pressed, false if released
|
||||
*/
|
||||
PointerCamera.prototype.onKeyEvent = function(event, toSet) {
|
||||
// Create copy of state
|
||||
var motionJsonCopy = JSON.stringify(this.motion);
|
||||
|
||||
switch ( event.keyCode ) {
|
||||
// Azerty keyboards
|
||||
case 38: case 90: this.motion.moveForward = toSet; break; // up / z
|
||||
case 37: case 81: this.motion.moveLeft = toSet; break; // left / q
|
||||
case 40: case 83: this.motion.moveBackward = toSet; break; // down / s
|
||||
case 39: case 68: this.motion.moveRight = toSet; break; // right / d
|
||||
case 32: this.motion.boost = toSet; break;
|
||||
|
||||
// Qwerty keyboards
|
||||
case 38: case 87: this.motion.moveForward = toSet; break; // up / w
|
||||
case 37: case 65: this.motion.moveLeft = toSet; break; // left / a
|
||||
case 40: case 83: this.motion.moveBackward = toSet; break; // down / s
|
||||
case 39: case 68: this.motion.moveRight = toSet; break; // right / d
|
||||
|
||||
case 73: case 104: this.motion.increasePhi = toSet; break; // 8 Up for angle
|
||||
case 75: case 98: this.motion.decreasePhi = toSet; break; // 2 Down for angle
|
||||
case 74: case 100: this.motion.increaseTheta = toSet; break; // 4 Left for angle
|
||||
case 76: case 102: this.motion.decreaseTheta = toSet; break; // 6 Right for angle
|
||||
|
||||
case 13: if (toSet) this.log(); break;
|
||||
}
|
||||
if (motionJsonCopy != JSON.stringify(this.motion)) {
|
||||
// Log any change
|
||||
var e = new BD.Event.KeyboardEvent();
|
||||
e.camera = this;
|
||||
e.send();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Manages the key pressed events
|
||||
* @param {event} event the event to manage
|
||||
*/
|
||||
PointerCamera.prototype.onKeyDown = function(event) {
|
||||
this.onKeyEvent(event, true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Manages the key released events
|
||||
* @param {event} event the event to manage
|
||||
*/
|
||||
PointerCamera.prototype.onKeyUp = function(event) {
|
||||
this.onKeyEvent(event, false);
|
||||
};
|
||||
|
||||
/**
|
||||
* Manages the mouse down events. Start drag'n'dropping if the options are set to drag'n'drop
|
||||
* @param {event} event the event to manage
|
||||
*/
|
||||
PointerCamera.prototype.onMouseDown = function(event) {
|
||||
|
||||
if (!this.shouldLock) {
|
||||
|
||||
this.mouse.x = ( ( event.clientX - this.renderer.domElement.offsetLeft ) / this.renderer.domElement.width ) * 2 - 1;
|
||||
this.mouse.y = - ( ( event.clientY - this.renderer.domElement.offsetTop ) / this.renderer.domElement.height ) * 2 + 1;
|
||||
|
||||
this.dragging = true;
|
||||
this.mouseMoved = false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Manages the mouse move events. Modifies the target of the camera according to the drag'n'drop motion
|
||||
* @param {event} event the event to manage
|
||||
*/
|
||||
PointerCamera.prototype.onMouseMove = function(event) {
|
||||
|
||||
if (!this.shouldLock && this.dragging) {
|
||||
var mouse = {x: this.mouse.x, y: this.mouse.y};
|
||||
this.mouse.x = ( ( event.clientX - this.renderer.domElement.offsetLeft ) / this.renderer.domElement.width ) * 2 - 1;
|
||||
this.mouse.y = - ( ( event.clientY - this.renderer.domElement.offsetTop ) / this.renderer.domElement.height ) * 2 + 1;
|
||||
|
||||
this.mouseMove.x = this.mouse.x - mouse.x;
|
||||
this.mouseMove.y = this.mouse.y - mouse.y;
|
||||
|
||||
this.mouseMoved = true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Manages the mouse move envent in case of pointer lock
|
||||
* @param {event} event the event to manage
|
||||
*/
|
||||
PointerCamera.prototype.onMouseMovePointer = function(e) {
|
||||
|
||||
if (this.isLocked()) {
|
||||
|
||||
// Backup theta and phi
|
||||
this.previousTheta = this.theta;
|
||||
this.previousPhi = this.phi;
|
||||
|
||||
this.mouseMove.x = e.movementX || e.mozMovementX || e.webkitMovementX || 0;
|
||||
this.mouseMove.y = e.movementY || e.mozMovementY || e.webkitMovementY || 0;
|
||||
|
||||
this.mouseMove.x *= -(this.sensitivity/5);
|
||||
this.mouseMove.y *= (this.sensitivity/5);
|
||||
|
||||
this.mouseMoved = true;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Manages the mouse up event. Stops the dragging
|
||||
* @param {event} event the event to manage
|
||||
*/
|
||||
PointerCamera.prototype.onMouseUp = function(event) {
|
||||
this.onMouseMove(event);
|
||||
|
||||
// Send log to DB
|
||||
if (this.dragging && this.mouseMoved && !this.moving && !this.movingHermite) {
|
||||
var e = new BD.Event.KeyboardEvent();
|
||||
e.camera = this;
|
||||
e.send();
|
||||
}
|
||||
|
||||
this.dragging = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Logs the camera to the terminal (pratical to create recommended views)
|
||||
*/
|
||||
PointerCamera.prototype.log = function() {
|
||||
console.log("createCamera(\nnew THREE.Vector3(" + this.position.x + "," + this.position.y + ',' + this.position.z + '),\n' +
|
||||
"new THREE.Vector3(" + this.target.x + "," + this.target.y + ',' + this.target.z + ')\n)');
|
||||
};
|
||||
|
||||
/**
|
||||
* Save the current state of the camera in the history
|
||||
*/
|
||||
PointerCamera.prototype.save = function() {
|
||||
var backup = {};
|
||||
backup.position = this.position.clone();
|
||||
backup.target = this.target.clone();
|
||||
this.history.addState(backup);
|
||||
};
|
||||
|
||||
/**
|
||||
* Undo last motion according to the history
|
||||
*/
|
||||
PointerCamera.prototype.undo = function() {
|
||||
var move = this.history.undo();
|
||||
if (move !== undefined) {
|
||||
var event = new BD.Event.PreviousNextClicked();
|
||||
event.previous = true;
|
||||
event.camera = move;
|
||||
event.send();
|
||||
|
||||
this.move(move, false);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Redo last motion according to the history
|
||||
*/
|
||||
PointerCamera.prototype.redo = function() {
|
||||
var move = this.history.redo();
|
||||
if (move !== undefined) {
|
||||
var event = new BD.Event.PreviousNextClicked();
|
||||
event.previous = false;
|
||||
event.camera = move;
|
||||
event.send();
|
||||
|
||||
this.move(move, false);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if there is a undo possibility in the history
|
||||
* @returns {Boolean} true if undo is possible, false otherwise
|
||||
*/
|
||||
PointerCamera.prototype.undoable = function() {
|
||||
return this.history.undoable();
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if there is a redo possibility in the history
|
||||
* @returns {Boolean} true if redo is possible, false otherwise
|
||||
*/
|
||||
PointerCamera.prototype.redoable = function() {
|
||||
return this.history.redoable();
|
||||
};
|
||||
|
||||
PointerCamera.prototype.toList = function() {
|
||||
this.updateMatrix();
|
||||
this.updateMatrixWorld();
|
||||
|
||||
var frustum = new THREE.Frustum();
|
||||
var projScreenMatrix = new THREE.Matrix4();
|
||||
projScreenMatrix.multiplyMatrices(this.projectionMatrix, this.matrixWorldInverse);
|
||||
|
||||
frustum.setFromMatrix(new THREE.Matrix4().multiplyMatrices(this.projectionMatrix, this.matrixWorldInverse));
|
||||
|
||||
var ret =
|
||||
[[this.position.x, this.position.y, this.position.z],
|
||||
[this.target.x, this.target.y, this.target.z]];
|
||||
|
||||
for (var i = 0; i < frustum.planes.length; i++) {
|
||||
|
||||
var p = frustum.planes[i];
|
||||
|
||||
ret.push([
|
||||
p.normal.x, p.normal.y, p.normal.z, p.constant
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
202
js/l3d/src/cameras/ReplayCamera.js
Normal file
202
js/l3d/src/cameras/ReplayCamera.js
Normal file
@@ -0,0 +1,202 @@
|
||||
// class camera extends THREE.PerspectiveCamera
|
||||
var ReplayCamera = function() {
|
||||
THREE.PerspectiveCamera.apply(this, arguments);
|
||||
|
||||
this.coins = arguments[4];
|
||||
|
||||
this.started = false;
|
||||
this.counter = 0;
|
||||
|
||||
this.position = new THREE.Vector3();
|
||||
this.target = new THREE.Vector3();
|
||||
this.new_position = new THREE.Vector3();
|
||||
this.new_target = new THREE.Vector3();
|
||||
|
||||
var id = params.get.id;
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "/prototype/replay_info/" + id, true);
|
||||
|
||||
var self = this;
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState == 4 && xhr.status == 200) {
|
||||
self.path = JSON.parse(xhr.responseText);
|
||||
self.started = true;
|
||||
self.nextEvent();
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
|
||||
// Set Position
|
||||
this.theta = Math.PI;
|
||||
this.phi = Math.PI;
|
||||
|
||||
this.resetElements = resetBobombElements();
|
||||
|
||||
};
|
||||
ReplayCamera.prototype = Object.create(THREE.PerspectiveCamera.prototype);
|
||||
ReplayCamera.prototype.constructor = ReplayCamera;
|
||||
|
||||
ReplayCamera.prototype.look = function() {
|
||||
this.lookAt(this.target);
|
||||
};
|
||||
|
||||
// Update function
|
||||
ReplayCamera.prototype.update = function(time) {
|
||||
if (this.started) {
|
||||
if (this.event.type == 'camera') {
|
||||
this.cameraMotion(time);
|
||||
} else if (this.event.type == 'previousnext') {
|
||||
this.linearMotion(time / 5);
|
||||
} else if (this.event.type == 'arrow') {
|
||||
this.hermiteMotion(time);
|
||||
}
|
||||
// } else if (this.event.type == 'coin') {
|
||||
// // Nothing to do
|
||||
// } else if (this.event.type == 'reset') {
|
||||
// // Nothing to do
|
||||
// }
|
||||
}
|
||||
};
|
||||
|
||||
ReplayCamera.prototype.linearMotion = function(time) {
|
||||
var tmp = Tools.sum(Tools.mul(this.old_position, 1-this.t), Tools.mul(this.new_position, this.t));
|
||||
this.position.x = tmp.x;
|
||||
this.position.y = tmp.y;
|
||||
this.position.z = tmp.z;
|
||||
this.t += 0.1 * time / 20;
|
||||
|
||||
if (this.t > 1) {
|
||||
this.nextEvent();
|
||||
}
|
||||
};
|
||||
|
||||
ReplayCamera.prototype.cameraMotion = function(time) {
|
||||
|
||||
var tmp = Tools.sum(Tools.mul(this.old_position, 1-this.t), Tools.mul(this.new_position, this.t));
|
||||
this.position.x = tmp.x;
|
||||
this.position.y = tmp.y;
|
||||
this.position.z = tmp.z;
|
||||
this.target = Tools.sum(Tools.mul(this.old_target, 1-this.t), Tools.mul(this.new_target, this.t));
|
||||
this.t += 1 / (((new Date(this.path[this.counter].time)).getTime() - (new Date(this.path[this.counter-1].time)).getTime()) / 20);
|
||||
|
||||
if (this.t > 1) {
|
||||
this.nextEvent();
|
||||
}
|
||||
};
|
||||
|
||||
ReplayCamera.prototype.hermiteMotion = function(time) {
|
||||
var e = this.hermitePosition.eval(this.t);
|
||||
this.position.x = e.x;
|
||||
this.position.y = e.y;
|
||||
this.position.z = e.z;
|
||||
|
||||
this.target = Tools.sum(this.position, this.hermiteAngles.eval(this.t));
|
||||
|
||||
this.t += 0.01 * time / 20;
|
||||
|
||||
if (this.t > 1) {
|
||||
this.nextEvent();
|
||||
}
|
||||
};
|
||||
|
||||
ReplayCamera.prototype.nextEvent = function() {
|
||||
this.counter++;
|
||||
|
||||
// Finished
|
||||
if (this.counter >= this.path.length) {
|
||||
this.started = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.event = this.path[this.counter];
|
||||
|
||||
if (this.event.type == 'camera') {
|
||||
this.move(this.event);
|
||||
} else if (this.event.type == 'coin') {
|
||||
this.coins[this.event.id].get();
|
||||
// Wait a little before launching nextEvent
|
||||
(function(self) {
|
||||
setTimeout(function() {
|
||||
self.nextEvent();
|
||||
},500);
|
||||
})(this);
|
||||
} else if (this.event.type == 'arrow') {
|
||||
this.moveHermite(this.cameras.cameras[this.event.id]);
|
||||
} else if (this.event.type == 'reset') {
|
||||
this.reset();
|
||||
(function (self) {
|
||||
setTimeout(function() {
|
||||
self.nextEvent();
|
||||
},500);
|
||||
})(this);
|
||||
} else if (this.event.type == 'previousnext') {
|
||||
this.move(this.event);
|
||||
} else if (this.event.type == 'hovered') {
|
||||
this.nextEvent();
|
||||
}
|
||||
};
|
||||
|
||||
ReplayCamera.prototype.reset = function() {
|
||||
this.resetPosition();
|
||||
this.moving = false;
|
||||
this.movingHermite = false;
|
||||
};
|
||||
|
||||
ReplayCamera.prototype.resetPosition = function() {
|
||||
this.position.copy(this.resetElements.position);
|
||||
this.target.copy(this.resetElements.target);
|
||||
this.anglesFromVectors();
|
||||
};
|
||||
|
||||
ReplayCamera.prototype.vectorsFromAngles = function() {
|
||||
// Update direction
|
||||
this.forward.y = Math.sin(this.phi);
|
||||
|
||||
var cos = Math.cos(this.phi);
|
||||
this.forward.z = cos * Math.cos(this.theta);
|
||||
this.forward.x = cos * Math.sin(this.theta);
|
||||
this.forward.normalize();
|
||||
|
||||
};
|
||||
|
||||
ReplayCamera.prototype.anglesFromVectors = function() {
|
||||
// Update phi and theta so that return to reality does not hurt
|
||||
var forward = Tools.diff(this.target, this.position);
|
||||
forward.normalize();
|
||||
|
||||
this.phi = Math.asin(forward.y);
|
||||
|
||||
// Don't know why this line works... But thanks Thierry-san and
|
||||
// Bastien because it seems to work...
|
||||
this.theta = Math.atan2(forward.x, forward.z);
|
||||
};
|
||||
|
||||
ReplayCamera.prototype.move = function(otherCamera) {
|
||||
this.moving = true;
|
||||
this.old_target = this.target.clone();
|
||||
this.old_position = this.position.clone();
|
||||
this.new_target = new THREE.Vector3(otherCamera.target.x, otherCamera.target.y, otherCamera.target.z);
|
||||
this.new_position = new THREE.Vector3(otherCamera.position.x, otherCamera.position.y, otherCamera.position.z);
|
||||
this.t = 0;
|
||||
|
||||
};
|
||||
|
||||
ReplayCamera.prototype.moveHermite = function(otherCamera) {
|
||||
this.movingHermite = true;
|
||||
this.t = 0;
|
||||
|
||||
this.hermitePosition = new Hermite.special.Polynom(
|
||||
this.position.clone(),
|
||||
otherCamera.position.clone(),
|
||||
Tools.mul(Tools.diff(otherCamera.target, otherCamera.position).normalize(),4)
|
||||
);
|
||||
|
||||
this.hermiteAngles = new Hermite.special.Polynom(
|
||||
Tools.diff(this.target, this.position),
|
||||
Tools.diff(otherCamera.target, otherCamera.position),
|
||||
new THREE.Vector3()
|
||||
);
|
||||
};
|
||||
|
||||
ReplayCamera.prototype.save = function() {};
|
||||
82
js/l3d/src/canvases/MousePointer.js
Normal file
82
js/l3d/src/canvases/MousePointer.js
Normal file
@@ -0,0 +1,82 @@
|
||||
var MousePointer = function(camera) {
|
||||
|
||||
this.domElement = document.createElement('canvas');
|
||||
this.domElement.style.position = 'absolute';
|
||||
this.domElement.style.cssFloat = 'top-left';
|
||||
this.ctx = this.domElement.getContext('2d');
|
||||
this.size = 10;
|
||||
this.drawn = false;
|
||||
camera.mousePointer = this;
|
||||
this.style = MousePointer.NONE;
|
||||
};
|
||||
|
||||
MousePointer.NONE = 0;
|
||||
MousePointer.BLACK = 1;
|
||||
MousePointer.RED = 2;
|
||||
|
||||
MousePointer.toColor = function(style) {
|
||||
|
||||
switch (style) {
|
||||
|
||||
case MousePointer.NONE:
|
||||
return null;
|
||||
case MousePointer.BLACK:
|
||||
return '#000000';
|
||||
case MousePointer.RED:
|
||||
return '#ff0000';
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
MousePointer.prototype.render = function(style) {
|
||||
|
||||
if (this.style !== style) {
|
||||
|
||||
if (style === MousePointer.NONE) {
|
||||
|
||||
// Clear canvas
|
||||
this.domElement.width = this.domElement.width;
|
||||
this.style = MousePointer.NONE;
|
||||
|
||||
} else {
|
||||
|
||||
this.domElement.width = this.domElement.width;
|
||||
|
||||
var i = container_size.width() / 2;
|
||||
var imin = i - this.size;
|
||||
var imax = i + this.size;
|
||||
|
||||
var j = container_size.height() / 2;
|
||||
var jmin = j - this.size;
|
||||
var jmax = j + this.size;
|
||||
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(imin, j);
|
||||
this.ctx.lineTo(imax, j);
|
||||
this.ctx.moveTo(i, jmin);
|
||||
this.ctx.lineTo(i, jmax);
|
||||
this.ctx.closePath();
|
||||
|
||||
|
||||
this.ctx.lineWidth = 5;
|
||||
this.ctx.strokeStyle = '#ffffff';
|
||||
this.ctx.stroke();
|
||||
|
||||
this.ctx.lineWidth = 2;
|
||||
this.ctx.strokeStyle = MousePointer.toColor(style);
|
||||
this.ctx.stroke();
|
||||
|
||||
this.style = style;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
MousePointer.prototype.clear = function() {
|
||||
|
||||
this.render(MousePointer.NONE);
|
||||
|
||||
};
|
||||
96
js/l3d/src/canvases/Previewer.js
Normal file
96
js/l3d/src/canvases/Previewer.js
Normal file
@@ -0,0 +1,96 @@
|
||||
Math.clamp = Math.clamp || function(number, min, max) {
|
||||
return Math.max(Math.min(number, max), min);
|
||||
};
|
||||
|
||||
var Previewer = function(renderer, scene) {
|
||||
this.domElement = document.createElement('canvas');
|
||||
this.ctx = this.domElement.getContext('2d');
|
||||
this.renderer = renderer;
|
||||
this.fixed = false;
|
||||
this.scene = scene;
|
||||
this.drawn = false;
|
||||
this.drawnBefore = false;
|
||||
};
|
||||
|
||||
Previewer.prototype.render = function(prev, container_width, container_height) {
|
||||
var width, height, left, bottom;
|
||||
|
||||
if (prev.go) {
|
||||
width = Math.floor(container_width / 5);
|
||||
height = Math.floor(container_height / 5);
|
||||
if (!this.fixed) {
|
||||
left = Math.floor(prev.x - width/2);
|
||||
bottom = Math.floor(this.renderer.domElement.height - prev.y + height/5);
|
||||
|
||||
// Translate box if too high
|
||||
if (bottom + height > this.renderer.domElement.height) {
|
||||
bottom -= 7 * height / 5;
|
||||
}
|
||||
|
||||
// Translate box if too on the side
|
||||
left = Math.clamp(left, width / 5, this.renderer.domElement.width - 6 * width / 5);
|
||||
|
||||
} else {
|
||||
left = 0;
|
||||
bottom = 0;
|
||||
}
|
||||
|
||||
// Draw border
|
||||
var can_bottom = container_height - bottom - height ;
|
||||
this.ctx.strokeStyle = "#ffffff";
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(left-1, can_bottom);
|
||||
this.ctx.lineTo(left-1, can_bottom + height);
|
||||
this.ctx.lineTo(left + width-1, can_bottom + height);
|
||||
this.ctx.lineTo(left + width-1, can_bottom);
|
||||
this.ctx.closePath();
|
||||
this.ctx.stroke();
|
||||
|
||||
this.ctx.strokeStyle = "#000000";
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(left, can_bottom + 1);
|
||||
this.ctx.lineTo(left, can_bottom + height - 1);
|
||||
this.ctx.lineTo(left + width - 2 , can_bottom + height-1);
|
||||
this.ctx.lineTo(left + width - 2, can_bottom+1);
|
||||
this.ctx.closePath();
|
||||
this.ctx.stroke();
|
||||
|
||||
// Do render in previsualization
|
||||
prev.camera.look();
|
||||
this.renderer.setScissor(left, bottom, width, height);
|
||||
this.renderer.enableScissorTest(true);
|
||||
this.renderer.setViewport(left, bottom, width, height);
|
||||
this.renderer.render(this.scene, prev.camera);
|
||||
|
||||
this.update(true);
|
||||
|
||||
if (this.prevCamera !== prev.camera) {
|
||||
this.clearNeeded = true;
|
||||
}
|
||||
|
||||
this.prevCamera = prev.camera;
|
||||
} else {
|
||||
this.update(false);
|
||||
}
|
||||
|
||||
if (this.drawnBefore && !this.drawn) {
|
||||
this.clearNeeded = true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Previewer.prototype.clear = function() {
|
||||
if (this.clearNeeded) {
|
||||
this.domElement.width = this.domElement.width;
|
||||
this.clearNeeded = false;
|
||||
}
|
||||
};
|
||||
|
||||
Previewer.prototype.fixedRecommendation = function(bool) {
|
||||
this.fixed = bool;
|
||||
};
|
||||
|
||||
Previewer.prototype.update = function(arg) {
|
||||
this.drawnBefore = this.drawn;
|
||||
this.drawn = arg;
|
||||
};
|
||||
44
js/l3d/src/canvases/StartCanvas.js
Normal file
44
js/l3d/src/canvases/StartCanvas.js
Normal file
@@ -0,0 +1,44 @@
|
||||
var StartCanvas = function(camera) {
|
||||
|
||||
this.domElement = document.createElement('canvas');
|
||||
this.domElement.style.position = 'absolute';
|
||||
this.domElement.style.cssFloat = 'top-left';
|
||||
this.ctx = this.domElement.getContext('2d');
|
||||
this.shown = false;
|
||||
|
||||
camera.startCanvas = this;
|
||||
|
||||
};
|
||||
|
||||
StartCanvas.prototype.render = function() {
|
||||
|
||||
if (!this.shown) {
|
||||
|
||||
this.ctx.fillStyle = 'white';
|
||||
this.ctx.globalAlpha = 0.7;
|
||||
this.ctx.fillRect(0,0,this.domElement.width, this.domElement.height);
|
||||
|
||||
this.ctx.font = '30px Verdana';
|
||||
this.ctx.globalAlpha = 1;
|
||||
this.ctx.fillStyle = 'black';
|
||||
this.ctx.fillText('Click here to lock the pointer !', container_size.width()/3.25, container_size.height()/2-10);
|
||||
|
||||
|
||||
this.shown = true;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
StartCanvas.prototype.clear = function() {
|
||||
|
||||
if (this.shown) {
|
||||
|
||||
// Clear canvas
|
||||
this.domElement.width = this.domElement.width;
|
||||
|
||||
this.shown = false;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
286
js/l3d/src/loaders/ProgressiveLoader.js
Normal file
286
js/l3d/src/loaders/ProgressiveLoader.js
Normal file
@@ -0,0 +1,286 @@
|
||||
var _parseList = function(arr) {
|
||||
|
||||
var ret = {};
|
||||
ret.index = arr[1];
|
||||
|
||||
if (arr[0] === 'v') {
|
||||
ret.type = 'vertex';
|
||||
ret.x = arr[2];
|
||||
ret.y = arr[3];
|
||||
ret.z = arr[4];
|
||||
} else if (arr[0] === 'vt') {
|
||||
ret.type = 'texCoord';
|
||||
ret.x = arr[2];
|
||||
ret.y = arr[3];
|
||||
} else if (arr[0] === 'f') {
|
||||
ret.type = 'face';
|
||||
|
||||
// Only Face3 are allowed
|
||||
vertexIndices = arr[2];
|
||||
textureIndices = arr[3];
|
||||
normalIndices = arr[4];
|
||||
|
||||
// Vertex indices
|
||||
ret.a = vertexIndices[0];
|
||||
ret.b = vertexIndices[1];
|
||||
ret.c = vertexIndices[2];
|
||||
|
||||
// Texutre indices (if they exist)
|
||||
if (textureIndices.length > 0) {
|
||||
ret.aTexture = textureIndices[0];
|
||||
ret.bTexture = textureIndices[1];
|
||||
ret.cTexture = textureIndices[2];
|
||||
}
|
||||
|
||||
// Normal indices (if they exist)
|
||||
if (normalIndices.length > 0) {
|
||||
ret.aNormal = normalIndices[0];
|
||||
ret.bNormal = normalIndices[1];
|
||||
ret.cNormal = normalIndices[2];
|
||||
}
|
||||
|
||||
} else if (arr[0] === 'vn') {
|
||||
|
||||
// Normal
|
||||
ret.type = "normal";
|
||||
ret.x = arr[2];
|
||||
ret.y = arr[3];
|
||||
ret.z = arr[4];
|
||||
|
||||
} else if (arr[0] === 'u') {
|
||||
|
||||
// usemtl
|
||||
ret.index = -1;
|
||||
ret.type = 'usemtl';
|
||||
ret.materialName = arr[1];
|
||||
ret.vLength = arr[2];
|
||||
ret.fLength = arr[3];
|
||||
ret.texCoordsExist = arr[4];
|
||||
ret.normalsExist = arr[5];
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
var ProgressiveLoader = function(path, scene, camera, callback) {
|
||||
// Init attributes
|
||||
this.objPath = path.substring(1, path.length);
|
||||
this.texturesPath = path.substring(0, path.lastIndexOf('/')) + '/';
|
||||
this.mtlPath = path.replace('.obj', '.mtl');
|
||||
this.scene = scene;
|
||||
this.callback = callback;
|
||||
this.counter = 0;
|
||||
|
||||
this.obj = new THREE.Object3D();
|
||||
|
||||
scene.add(this.obj);
|
||||
|
||||
this.vertices = [];
|
||||
this.texCoords = [];
|
||||
this.normals = [];
|
||||
|
||||
// Init MTLLoader
|
||||
this.loader = new THREE.MTLLoader(this.texturesPath);
|
||||
|
||||
// Init io stuff
|
||||
this.socket = io();
|
||||
this.initIOCallbacks();
|
||||
|
||||
this.camera = camera;
|
||||
|
||||
};
|
||||
|
||||
ProgressiveLoader.prototype.load = function() {
|
||||
|
||||
var self = this;
|
||||
|
||||
this.loader.load(self.mtlPath, function(materialCreator) {
|
||||
|
||||
self.materialCreator = materialCreator;
|
||||
|
||||
materialCreator.preload();
|
||||
|
||||
self.start();
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
ProgressiveLoader.prototype.initIOCallbacks = function() {
|
||||
|
||||
var self = this;
|
||||
|
||||
this.socket.on('ok', function() {
|
||||
console.log('ok');
|
||||
self.socket.emit('next');
|
||||
});
|
||||
|
||||
this.socket.on('elements', function(arr) {
|
||||
|
||||
// console.log("Received elements for the " + (++self.counter) + "th time !");
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
|
||||
var elt = _parseList(arr[i]);
|
||||
|
||||
// console.log(elts);
|
||||
if (elt.type === 'vertex') {
|
||||
|
||||
// New vertex arrived
|
||||
self.vertices[elt.index] = [elt.x, elt.y, elt.z];
|
||||
|
||||
} else if (elt.type === 'texCoord') {
|
||||
|
||||
// New texCoord arrived
|
||||
self.texCoords[elt.index] = [elt.x, elt.y];
|
||||
|
||||
} else if (elt.type === 'normal') {
|
||||
|
||||
// New normal arrived
|
||||
self.normals[elt.index] = [elt.x, elt.y, elt.z];
|
||||
|
||||
} else if (elt.type === 'usemtl') {
|
||||
|
||||
if (self.currentMesh !== undefined) {
|
||||
|
||||
self.currentMesh.geometry.computeBoundingSphere();
|
||||
|
||||
if (self.currentMesh.geometry.attributes.normal === undefined) {
|
||||
|
||||
self.currentMesh.geometry.computeVertexNormals();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Must create new mesh
|
||||
// console.log("New mesh arrived : " + elt.materialName);
|
||||
|
||||
// Create mesh material
|
||||
var material;
|
||||
|
||||
if (elt.materialName === null) {
|
||||
|
||||
// If no material, create a default material
|
||||
material = new THREE.MeshLambertMaterial({color: 'red'});
|
||||
|
||||
} else {
|
||||
|
||||
// If material name exists, load if from material, and do a couple of settings
|
||||
material = self.materialCreator.materials[elt.materialName.trim()];
|
||||
|
||||
material.side = THREE.DoubleSide;
|
||||
|
||||
if (material.map)
|
||||
material.map.wrapS = material.map.wrapT = THREE.RepeatWrapping;
|
||||
}
|
||||
|
||||
// Create mesh geometry
|
||||
var geometry = new THREE.BufferGeometry();
|
||||
geometry.dynamic = true;
|
||||
|
||||
var positionArray = new Float32Array(elt.fLength * 3 * 3);
|
||||
var positionAttribute = new THREE.BufferAttribute(positionArray, 3);
|
||||
|
||||
geometry.addAttribute('position', positionAttribute);
|
||||
|
||||
// Add other attributes if necessary
|
||||
if (elt.texCoordsExist) {
|
||||
|
||||
// console.log("Mesh with textures");
|
||||
|
||||
var uvArray = new Float32Array(elt.fLength * 3 * 2);
|
||||
var uvAttribute = new THREE.BufferAttribute(uvArray, 2);
|
||||
|
||||
geometry.addAttribute('uv', uvAttribute);
|
||||
}
|
||||
|
||||
if (elt.normalsExist) {
|
||||
|
||||
// console.log("Mesh with normals");
|
||||
|
||||
var normalArray = new Float32Array(elt.fLength * 3 * 3);
|
||||
var normalAttribute = new THREE.BufferAttribute(normalArray, 3);
|
||||
|
||||
geometry.addAttribute('normal', normalAttribute);
|
||||
|
||||
}
|
||||
|
||||
// Create mesh
|
||||
var mesh = new THREE.Mesh(geometry, material);
|
||||
|
||||
self.currentMesh = mesh;
|
||||
self.obj.add(mesh);
|
||||
|
||||
if (typeof self.callback === 'function') {
|
||||
self.callback(mesh);
|
||||
}
|
||||
|
||||
} else if (elt.type === 'face') {
|
||||
|
||||
// New face arrived : add it into current mesh
|
||||
self.currentMesh.geometry.attributes.position.array[elt.index * 9 ] = self.vertices[elt.a][0];
|
||||
self.currentMesh.geometry.attributes.position.array[elt.index * 9 + 1] = self.vertices[elt.a][1];
|
||||
self.currentMesh.geometry.attributes.position.array[elt.index * 9 + 2] = self.vertices[elt.a][2];
|
||||
|
||||
self.currentMesh.geometry.attributes.position.array[elt.index * 9 + 3] = self.vertices[elt.b][0];
|
||||
self.currentMesh.geometry.attributes.position.array[elt.index * 9 + 4] = self.vertices[elt.b][1];
|
||||
self.currentMesh.geometry.attributes.position.array[elt.index * 9 + 5] = self.vertices[elt.b][2];
|
||||
|
||||
self.currentMesh.geometry.attributes.position.array[elt.index * 9 + 6] = self.vertices[elt.c][0];
|
||||
self.currentMesh.geometry.attributes.position.array[elt.index * 9 + 7] = self.vertices[elt.c][1];
|
||||
self.currentMesh.geometry.attributes.position.array[elt.index * 9 + 8] = self.vertices[elt.c][2];
|
||||
|
||||
self.currentMesh.geometry.attributes.position.needsUpdate = true;
|
||||
|
||||
// If normals
|
||||
if (elt.aNormal !== undefined) {
|
||||
|
||||
self.currentMesh.geometry.attributes.normal.array[elt.index * 9 ] = self.normals[elt.aNormal][0];
|
||||
self.currentMesh.geometry.attributes.normal.array[elt.index * 9 + 1] = self.normals[elt.aNormal][1];
|
||||
self.currentMesh.geometry.attributes.normal.array[elt.index * 9 + 2] = self.normals[elt.aNormal][2];
|
||||
|
||||
self.currentMesh.geometry.attributes.normal.array[elt.index * 9 + 3] = self.normals[elt.bNormal][0];
|
||||
self.currentMesh.geometry.attributes.normal.array[elt.index * 9 + 4] = self.normals[elt.bNormal][1];
|
||||
self.currentMesh.geometry.attributes.normal.array[elt.index * 9 + 5] = self.normals[elt.bNormal][2];
|
||||
|
||||
self.currentMesh.geometry.attributes.normal.array[elt.index * 9 + 6] = self.normals[elt.cNormal][0];
|
||||
self.currentMesh.geometry.attributes.normal.array[elt.index * 9 + 7] = self.normals[elt.cNormal][1];
|
||||
self.currentMesh.geometry.attributes.normal.array[elt.index * 9 + 8] = self.normals[elt.cNormal][2];
|
||||
|
||||
self.currentMesh.geometry.attributes.normal.needsUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
if (elt.aTexture !== undefined) {
|
||||
|
||||
self.currentMesh.geometry.attributes.uv.array[elt.index * 6 ] = self.texCoords[elt.aTexture][0];
|
||||
self.currentMesh.geometry.attributes.uv.array[elt.index * 6 + 1] = self.texCoords[elt.aTexture][1];
|
||||
|
||||
self.currentMesh.geometry.attributes.uv.array[elt.index * 6 + 2] = self.texCoords[elt.bTexture][0];
|
||||
self.currentMesh.geometry.attributes.uv.array[elt.index * 6 + 3] = self.texCoords[elt.bTexture][1];
|
||||
|
||||
self.currentMesh.geometry.attributes.uv.array[elt.index * 6 + 4] = self.texCoords[elt.cTexture][0];
|
||||
self.currentMesh.geometry.attributes.uv.array[elt.index * 6 + 5] = self.texCoords[elt.cTexture][1];
|
||||
|
||||
self.currentMesh.geometry.attributes.uv.needsUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Ask for next elements
|
||||
self.socket.emit('next');
|
||||
});
|
||||
|
||||
this.socket.on('disconnect', function() {
|
||||
console.log('Finished !');
|
||||
self.finished = true;
|
||||
});
|
||||
};
|
||||
|
||||
ProgressiveLoader.prototype.start = function() {
|
||||
this.socket.emit('request', this.objPath);
|
||||
};
|
||||
|
||||
377
js/l3d/src/loaders/ProgressiveLoaderGeometry.js
Normal file
377
js/l3d/src/loaders/ProgressiveLoaderGeometry.js
Normal file
@@ -0,0 +1,377 @@
|
||||
/**
|
||||
* Parse a list as it is sent by the server and gives a slightly more comprehensible result
|
||||
* @private
|
||||
*/
|
||||
var _parseList2 = function(arr) {
|
||||
|
||||
var ret = {};
|
||||
ret.index = arr[1];
|
||||
|
||||
if (arr[0] === 'v') {
|
||||
ret.type = 'vertex';
|
||||
ret.x = arr[2];
|
||||
ret.y = arr[3];
|
||||
ret.z = arr[4];
|
||||
} else if (arr[0] === 'vt') {
|
||||
ret.type = 'texCoord';
|
||||
ret.x = arr[2];
|
||||
ret.y = arr[3];
|
||||
} else if (arr[0] === 'f') {
|
||||
ret.type = 'face';
|
||||
ret.mesh = arr[2];
|
||||
|
||||
// Only Face3 are allowed
|
||||
vertexIndices = arr[3];
|
||||
textureIndices = arr[4];
|
||||
normalIndices = arr[5];
|
||||
|
||||
// Vertex indices
|
||||
ret.a = vertexIndices[0];
|
||||
ret.b = vertexIndices[1];
|
||||
ret.c = vertexIndices[2];
|
||||
|
||||
// Texutre indices (if they exist)
|
||||
if (textureIndices.length > 0) {
|
||||
ret.aTexture = textureIndices[0];
|
||||
ret.bTexture = textureIndices[1];
|
||||
ret.cTexture = textureIndices[2];
|
||||
}
|
||||
|
||||
// Normal indices (if they exist)
|
||||
if (normalIndices.length > 0) {
|
||||
ret.aNormal = normalIndices[0];
|
||||
ret.bNormal = normalIndices[1];
|
||||
ret.cNormal = normalIndices[2];
|
||||
}
|
||||
|
||||
} else if (arr[0] === 'vn') {
|
||||
|
||||
// Normal
|
||||
ret.type = "normal";
|
||||
ret.x = arr[2];
|
||||
ret.y = arr[3];
|
||||
ret.z = arr[4];
|
||||
|
||||
} else if (arr[0] === 'u') {
|
||||
|
||||
// usemtl
|
||||
ret.index = -1;
|
||||
ret.type = 'usemtl';
|
||||
ret.materialName = arr[1];
|
||||
ret.vLength = arr[2];
|
||||
ret.fLength = arr[3];
|
||||
ret.texCoordsExist = arr[4];
|
||||
ret.normalsExist = arr[5];
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads a mesh from socket.io
|
||||
* @param {string} path path to the .obj file
|
||||
* @param {THREE.Scene} scene to add the object
|
||||
* @param {PointerCamera} camera the camera that will be sent to server for smart
|
||||
* streaming (can be null, then the server will stream the mesh in the .obj
|
||||
* order)
|
||||
* @param {function} callback callback to call on the objects when they're created
|
||||
* @constructor
|
||||
*/
|
||||
var ProgressiveLoaderGeometry = function(path, scene, camera, callback) {
|
||||
|
||||
/**
|
||||
* Path to the .obj file
|
||||
* @type {string}
|
||||
*/
|
||||
this.objPath = path;
|
||||
|
||||
/**
|
||||
* Path to the folder where the textures are
|
||||
* @type {string}
|
||||
*/
|
||||
this.texturesPath = path.substring(0, path.lastIndexOf('/')) + '/';
|
||||
|
||||
/**
|
||||
* Path to the .mtl file
|
||||
* @type {string}
|
||||
*/
|
||||
this.mtlPath = path.replace('.obj', '.mtl');
|
||||
|
||||
/**
|
||||
* Reference to the scene in which the object should be added
|
||||
*/
|
||||
this.scene = scene;
|
||||
|
||||
/**
|
||||
* Callback to call on the object when they're created
|
||||
*/
|
||||
this.callback = callback;
|
||||
|
||||
/**
|
||||
* Counter (not used)
|
||||
* @private
|
||||
*/
|
||||
this.counter = 0;
|
||||
|
||||
/**
|
||||
* Group where the sub-objects will be added
|
||||
* @type {THREE.Object3D}
|
||||
*/
|
||||
this.obj = new THREE.Object3D();
|
||||
|
||||
scene.add(this.obj);
|
||||
|
||||
/**
|
||||
* Array of the vertices of the mesh
|
||||
* @type {THREE.Vector3[]}
|
||||
*/
|
||||
this.vertices = [];
|
||||
|
||||
/**
|
||||
* Array of the texture coordinates of the mesh
|
||||
* @type {THREE.Vector2[]}
|
||||
*/
|
||||
this.texCoords = [];
|
||||
|
||||
/**
|
||||
* Array of the normal of the mesh
|
||||
* @type {THREE.Vector3[]}
|
||||
*/
|
||||
this.normals = [];
|
||||
|
||||
/**
|
||||
* Array of the UV mapping
|
||||
* @description Each element is an array of 3 elements that are the indices
|
||||
* of the element in <code>this.texCoords</code> that should be
|
||||
* used as texture coordinates for the current vertex of the face
|
||||
* @type {Number[][]}
|
||||
*/
|
||||
this.uvs = [];
|
||||
|
||||
/**
|
||||
* Array of all the meshes that will be added to the main object
|
||||
* @type {THREE.Mesh[]}
|
||||
*/
|
||||
this.meshes = [];
|
||||
|
||||
/**
|
||||
* Loader for the material file
|
||||
* @type {THREE.MTLLoader}
|
||||
*/
|
||||
this.loader = new THREE.MTLLoader(this.texturesPath);
|
||||
|
||||
/**
|
||||
* Socket to connect to get the mesh
|
||||
* @type {socket}
|
||||
*/
|
||||
this.socket = io();
|
||||
|
||||
this.initIOCallbacks();
|
||||
|
||||
/**
|
||||
* Reference to the camera
|
||||
* @type {PointerCamera}
|
||||
*/
|
||||
this.camera = camera;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Starts the loading of the mesh
|
||||
*/
|
||||
ProgressiveLoaderGeometry.prototype.load = function() {
|
||||
|
||||
var self = this;
|
||||
|
||||
this.loader.load(self.mtlPath, function(materialCreator) {
|
||||
|
||||
self.materialCreator = materialCreator;
|
||||
|
||||
materialCreator.preload();
|
||||
|
||||
self.start();
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Will return a list representation of the camera (to be sent to the server)
|
||||
*/
|
||||
ProgressiveLoaderGeometry.prototype.getCamera = function() {
|
||||
if (this.camera === null)
|
||||
return null;
|
||||
|
||||
return this.toList();
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes the socket.io functions so that it can discuss with the server
|
||||
*/
|
||||
ProgressiveLoaderGeometry.prototype.initIOCallbacks = function() {
|
||||
|
||||
var self = this;
|
||||
|
||||
this.socket.on('ok', function() {
|
||||
console.log('ok');
|
||||
self.socket.emit('materials');
|
||||
});
|
||||
|
||||
this.socket.on('elements', function(arr) {
|
||||
|
||||
if (arr.length === 0) {
|
||||
|
||||
console.log("Empty array");
|
||||
|
||||
} else {
|
||||
|
||||
console.log("Stuff received");
|
||||
|
||||
}
|
||||
|
||||
|
||||
// console.log("Received elements for the " + (++self.counter) + "th time !");
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
|
||||
var elt = _parseList2(arr[i]);
|
||||
|
||||
// console.log(elts);
|
||||
if (elt.type === 'vertex') {
|
||||
|
||||
// New vertex arrived
|
||||
|
||||
// Fill the array of vertices with null vector (to avoid undefined)
|
||||
while (elt.index > self.vertices.length) {
|
||||
|
||||
self.vertices.push(new THREE.Vector3());
|
||||
|
||||
}
|
||||
|
||||
self.vertices[elt.index] = new THREE.Vector3(elt.x, elt.y, elt.z);
|
||||
self.currentMesh.geometry.verticesNeedUpdate = true;
|
||||
|
||||
} else if (elt.type === 'texCoord') {
|
||||
|
||||
// New texCoord arrived
|
||||
self.texCoords[elt.index] = new THREE.Vector2(elt.x, elt.y);
|
||||
self.currentMesh.geometry.uvsNeedUpdate = true;
|
||||
|
||||
} else if (elt.type === 'normal') {
|
||||
|
||||
// New normal arrived
|
||||
self.normals[elt.index] = new THREE.Vector3(elt.x, elt.y, elt.z);
|
||||
|
||||
} else if (elt.type === 'usemtl') {
|
||||
|
||||
if (self.currentMesh !== undefined) {
|
||||
|
||||
// if (self.currentMesh.geometry.attributes.normal === undefined) {
|
||||
|
||||
// self.currentMesh.geometry.computeVertexNormals();
|
||||
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
// Must create new mesh
|
||||
// console.log("New mesh arrived : " + elt.materialName);
|
||||
|
||||
// Create mesh material
|
||||
var material;
|
||||
|
||||
if (elt.materialName === null) {
|
||||
|
||||
// If no material, create a default material
|
||||
material = new THREE.MeshLambertMaterial({color: 'red'});
|
||||
|
||||
} else {
|
||||
|
||||
// If material name exists, load if from material, and do a couple of settings
|
||||
material = self.materialCreator.materials[elt.materialName.trim()];
|
||||
|
||||
material.side = THREE.DoubleSide;
|
||||
|
||||
if (material.map)
|
||||
material.map.wrapS = material.map.wrapT = THREE.RepeatWrapping;
|
||||
}
|
||||
|
||||
// Create mesh geometry
|
||||
self.uvs = [];
|
||||
var geometry = new THREE.Geometry();
|
||||
geometry.vertices = self.vertices;
|
||||
geometry.faces = [];
|
||||
|
||||
// If texture coords, init faceVertexUvs attribute
|
||||
if (elt.texCoordsExist) {
|
||||
geometry.faceVertexUvs = [self.uvs];
|
||||
}
|
||||
|
||||
geometry.dynamic = true;
|
||||
|
||||
// Create mesh
|
||||
var mesh = new THREE.Mesh(geometry, material);
|
||||
mesh.faceNumber = elt.fLength;
|
||||
self.meshes.push(mesh);
|
||||
|
||||
self.currentMesh = mesh;
|
||||
|
||||
if (typeof self.callback === 'function') {
|
||||
self.callback(mesh);
|
||||
}
|
||||
|
||||
} else if (elt.type === 'face') {
|
||||
|
||||
if (!self.meshes[elt.mesh].added) {
|
||||
|
||||
self.meshes[elt.mesh].added = true;
|
||||
self.obj.add(self.meshes[elt.mesh]);
|
||||
|
||||
}
|
||||
|
||||
if (elt.aNormal !== undefined) {
|
||||
self.meshes[elt.mesh].geometry.faces.push(new THREE.Face3(elt.a, elt.b, elt.c, [self.normals[elt.aNormal], self.normals[elt.bNormal], self.normals[elt.cNormal]]));
|
||||
} else {
|
||||
self.meshes[elt.mesh].geometry.faces.push(new THREE.Face3(elt.a, elt.b, elt.c));
|
||||
self.meshes[elt.mesh].geometry.computeFaceNormals();
|
||||
self.meshes[elt.mesh].geometry.computeVertexNormals();
|
||||
}
|
||||
|
||||
if (elt.aTexture !== undefined) {
|
||||
|
||||
self.meshes[elt.mesh].geometry.faceVertexUvs[0].push([self.texCoords[elt.aTexture], self.texCoords[elt.bTexture], self.texCoords[elt.cTexture]]);
|
||||
|
||||
}
|
||||
|
||||
self.meshes[elt.mesh].geometry.verticesNeedUpdate = true;
|
||||
self.meshes[elt.mesh].geometry.uvsNeedUpdate = true;
|
||||
self.meshes[elt.mesh].geometry.normalsNeedUpdate = true;
|
||||
self.meshes[elt.mesh].geometry.groupsNeedUpdate = true;
|
||||
|
||||
if (self.meshes[elt.mesh].faceNumber === self.meshes[elt.mesh].geometry.faces.length) {
|
||||
|
||||
self.meshes[elt.mesh].geometry.computeBoundingSphere();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Ask for next elements
|
||||
self.socket.emit('next', self.getCamera());
|
||||
});
|
||||
|
||||
this.socket.on('disconnect', function() {
|
||||
console.log('Finished !');
|
||||
self.finished = true;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Starts the communication with the server
|
||||
*/
|
||||
ProgressiveLoaderGeometry.prototype.start = function() {
|
||||
this.socket.emit('request', this.objPath);
|
||||
};
|
||||
|
||||
201
js/l3d/src/math/Hermite.js
Normal file
201
js/l3d/src/math/Hermite.js
Normal file
@@ -0,0 +1,201 @@
|
||||
var Hermite = {};
|
||||
|
||||
Hermite.Polynom = function(t, f, fp) {
|
||||
this.times = t;
|
||||
this.evals = f;
|
||||
this.primes = fp;
|
||||
|
||||
this.baseFunctions = [];
|
||||
|
||||
for (var i in this.times) {
|
||||
this.baseFunctions.push(new Hermite.BaseFunction(i, this.times));
|
||||
}
|
||||
|
||||
// Let's do something at least a little reusable
|
||||
this.tools = {};
|
||||
if (f[0] instanceof THREE.Vector3) {
|
||||
this.tools.whatType = 'THREE.Vector3';
|
||||
this.tools.sum = Tools.sum;
|
||||
this.tools.prod = Tools.mul;
|
||||
} else {
|
||||
this.tools.whatType = 'number';
|
||||
this.tools.sum = function(a, b) { return a + b; };
|
||||
this.tools.prod = function(a, b) { return a * b; };
|
||||
}
|
||||
};
|
||||
|
||||
Hermite.Polynom.prototype.eval = function(t) {
|
||||
var ret;
|
||||
|
||||
if (this.tools.whatType === 'THREE.Vector3') {
|
||||
ret = new THREE.Vector3();
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
for (var i in this.times) {
|
||||
var ti = this.times[i];
|
||||
var qi_t = this.baseFunctions[i].eval(t);
|
||||
// var qi_ti = this.baseFunctions[i].eval(ti);
|
||||
|
||||
var qip_ti = this.baseFunctions[i].prime(ti);
|
||||
var f_ti = this.evals[i];
|
||||
var fp_ti = this.primes[i];
|
||||
|
||||
// This is the wikipedia formula
|
||||
// ret += (qi_t / qi_ti) * ((1 - (t - ti) * (qip_ti / qi_ti)) * f_ti + (t - ti) * fp_ti);
|
||||
// Let's not forget that qi_ti = 1
|
||||
|
||||
// This is the final formula
|
||||
// ret += (qi_t) * ((1 - (t - ti) * (qip_ti)) * f_ti + (t - ti) * fp_ti);
|
||||
|
||||
// This is the implementation working with THREE.Vector3
|
||||
// In terms of disgusting code, we're quite good there
|
||||
ret =
|
||||
this.tools.sum(
|
||||
ret,
|
||||
this.tools.prod(
|
||||
this.tools.sum(
|
||||
this.tools.prod(f_ti, 1 - (t - ti) * (qip_ti)),
|
||||
this.tools.prod(fp_ti, t - ti)
|
||||
),
|
||||
qi_t
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
Hermite.Polynom.prototype.prime = function(t) {
|
||||
var ret;
|
||||
|
||||
if (this.tools.whatType === 'THREE.Vector3') {
|
||||
ret = new THREE.Vector3();
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
for (var i in this.times) {
|
||||
var ti = this.times[i];
|
||||
var qi_t = this.baseFunctions[i].eval(t);
|
||||
// var qi_ti = this.baseFunctions[i].eval(ti);
|
||||
|
||||
var qip_t = this.baseFunctions[i].prime(t );
|
||||
var qip_ti = this.baseFunctions[i].prime(ti);
|
||||
var f_ti = this.evals[i];
|
||||
var fp_ti = this.primes[i];
|
||||
|
||||
// The return of the disgusting code...
|
||||
// First part is the same that the eval function, but changing qi_t by qip_t
|
||||
// (first part of the derivative)
|
||||
ret =
|
||||
this.tools.sum(
|
||||
ret,
|
||||
this.tools.prod(
|
||||
this.tools.sum(
|
||||
this.tools.prod(f_ti, 1 - (t - ti) * (qip_ti)),
|
||||
this.tools.prod(fp_ti, t - ti)
|
||||
),
|
||||
qip_t
|
||||
)
|
||||
);
|
||||
|
||||
// Here, we just add
|
||||
// ret += qi_t * (-qip_t * f_ti + fp_ti);
|
||||
ret =
|
||||
this.tools.sum(
|
||||
ret,
|
||||
this.tools.prod(
|
||||
this.tools.sum(
|
||||
this.tools.prod(
|
||||
f_ti,
|
||||
-qip_t
|
||||
),
|
||||
fp_ti
|
||||
),
|
||||
qi_t
|
||||
)
|
||||
);
|
||||
|
||||
// Now the following code is the same as the precedent affectation
|
||||
// However it doesn't work, and I can't see the difference between
|
||||
// this and the previous one... so I keep it here, to find the
|
||||
// mistate later
|
||||
// ret =
|
||||
// this.tools.sum(
|
||||
// ret,
|
||||
// this.tools.prod(
|
||||
// this.tools.sum(
|
||||
// fp_ti,
|
||||
// this.tools.prod(
|
||||
// f_ti,
|
||||
// -qip_ti
|
||||
// )
|
||||
// ),
|
||||
// qi_t
|
||||
// )
|
||||
// );
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
Hermite.BaseFunction = function(index, times) {
|
||||
this.index = index;
|
||||
this.times = times;
|
||||
};
|
||||
|
||||
Hermite.BaseFunction.prototype.eval = function(t) {
|
||||
var ret = 1;
|
||||
|
||||
for (var i in this.times) {
|
||||
if (i !== this.index) {
|
||||
ret *= (t - this.times[i]) / (this.times[this.index] - this.times[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return ret * ret;
|
||||
};
|
||||
|
||||
Hermite.BaseFunction.prototype.prime = function(t) {
|
||||
var ret = 0;
|
||||
|
||||
for (var i in this.times) {
|
||||
if (i !== this.index) {
|
||||
ret += 2 / (t - this.times[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return this.eval(t) * ret;
|
||||
};
|
||||
|
||||
Hermite.special = {};
|
||||
|
||||
// This polynom interpolates with two coords and one derivative
|
||||
// t = [0,1]
|
||||
Hermite.special.Polynom = function(P0, P1, PP1) {
|
||||
this.tools = {};
|
||||
if (P0 instanceof THREE.Vector3) {
|
||||
this.tools.sum = Tools.sum;
|
||||
this.tools.mul = Tools.mul;
|
||||
this.tools.diff = Tools.diff;
|
||||
this.c = P0.clone();
|
||||
} else {
|
||||
this.tools.sum = function(a,b) { return a+b; };
|
||||
this.tools.mul = function(a,b) { return a*b; };
|
||||
this.tools.diff = function(a,b) { return a-b; };
|
||||
this.c = P0;
|
||||
}
|
||||
|
||||
this.a = this.tools.sum(PP1, this.tools.diff(P0, P1));
|
||||
this.b = this.tools.diff(this.tools.mul(this.tools.diff(P1,P0), 2), PP1);
|
||||
};
|
||||
|
||||
Hermite.special.Polynom.prototype.eval = function(t) {
|
||||
return this.tools.sum(this.tools.mul(this.a, t*t), this.tools.sum(this.tools.mul(this.b, t), this.c));
|
||||
};
|
||||
|
||||
Hermite.special.Polynom.prototype.prime = function(t) {
|
||||
return this.tools.sum(this.tools.mul(this.a,2*t), this.b);
|
||||
};
|
||||
44
js/l3d/src/math/HermiteTest/HermiteTest.js
Normal file
44
js/l3d/src/math/HermiteTest/HermiteTest.js
Normal file
@@ -0,0 +1,44 @@
|
||||
var container = document.getElementById('content');
|
||||
|
||||
function print(text) {
|
||||
var content = document.createTextNode(text);
|
||||
var new_line = document.createElement('br');
|
||||
container.appendChild(content);
|
||||
container.appendChild(new_line);
|
||||
}
|
||||
|
||||
function toString(variable) {
|
||||
if (variable instanceof THREE.Vector3) {
|
||||
return variable.x + ', ' + variable.y + ', ' + variable.z;
|
||||
} else {
|
||||
return variable;
|
||||
}
|
||||
}
|
||||
|
||||
// Test with THREE.Vector3
|
||||
// t = [0,1];
|
||||
// f = [new THREE.Vector3(0,0,0), new THREE.Vector3(1,1,1)];
|
||||
// fp = [new THREE.Vector3(0,1,2), new THREE.Vector3(0,0,0)];
|
||||
|
||||
// Test with doubles
|
||||
t = [0,1];
|
||||
f = [0,1];
|
||||
fp = [-1,-1];
|
||||
|
||||
var hermite = new Hermite.special.Polynom(0, 1, -1);
|
||||
|
||||
print('M = [');
|
||||
for (var t = 0; t < 1; t += 0.01) {
|
||||
var res = hermite.eval(t);
|
||||
print("\t" + t + ',' + toString(res) + ';');
|
||||
}
|
||||
print('];');
|
||||
|
||||
print('MP = [');
|
||||
for (var t = 0; t < 1; t += 0.01) {
|
||||
var res = hermite.prime(t);
|
||||
print("\t" + t + ',' + toString(res) + ';');
|
||||
}
|
||||
print('];');
|
||||
|
||||
|
||||
37
js/l3d/src/math/Tools.js
Normal file
37
js/l3d/src/math/Tools.js
Normal file
@@ -0,0 +1,37 @@
|
||||
var Tools = {version : "1.0" };
|
||||
|
||||
Tools.sum = function(v1, v2) {
|
||||
return new THREE.Vector3(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
|
||||
};
|
||||
|
||||
Tools.diff = function(v1, v2) {
|
||||
return new THREE.Vector3(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
|
||||
};
|
||||
|
||||
Tools.dot = function(v1, v2) {
|
||||
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
|
||||
};
|
||||
|
||||
Tools.cross = function(v1, v2) {
|
||||
return new THREE.Vector3(
|
||||
v1.y * v2.z - v1.z * v2.y,
|
||||
v1.z * v2.x - v1.x * v2.z,
|
||||
v1.x * v2.y - v1.y * v2.x
|
||||
);
|
||||
};
|
||||
|
||||
Tools.mul = function(v1, lambda) {
|
||||
return new THREE.Vector3(v1.x * lambda, v1.y * lambda, v1.z * lambda);
|
||||
};
|
||||
|
||||
Tools.equals = function(v1, v2) {
|
||||
return v1.x == v2.x && v1.y == v2.y && v1.z == v2.z;
|
||||
};
|
||||
|
||||
Tools.norm2 = function(v) {
|
||||
return v.x * v.x + v.y * v.y + v.z * v.z;
|
||||
};
|
||||
|
||||
Tools.norm = function(v) {
|
||||
return Math.sqrt(Tools.norm2(v));
|
||||
};
|
||||
81
js/l3d/src/math/ToolsTest.js
Normal file
81
js/l3d/src/math/ToolsTest.js
Normal file
@@ -0,0 +1,81 @@
|
||||
// We will be doing a lot of document.write, so let's remove jshint warnings
|
||||
/* jshint evil:true */
|
||||
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();
|
||||
285
js/l3d/src/recommendations/ArrowCamera.js
Normal file
285
js/l3d/src/recommendations/ArrowCamera.js
Normal file
@@ -0,0 +1,285 @@
|
||||
// Initialization
|
||||
|
||||
// class camera extends THREE.PerspectiveCamera
|
||||
var ArrowCamera = function(arg1, arg2, arg3, arg4, position, target) {
|
||||
THREE.PerspectiveCamera.apply(this, arguments);
|
||||
|
||||
// Set Position
|
||||
if (position === undefined) {
|
||||
this.position = new THREE.Vector3(0,0,5);
|
||||
} else {
|
||||
this.position.x = position.x;
|
||||
this.position.y = position.y;
|
||||
this.position.z = position.z;
|
||||
}
|
||||
|
||||
if (target === undefined)
|
||||
target = new THREE.Vector3(0,0,0);
|
||||
|
||||
var direction = target.clone();
|
||||
direction.sub(this.position);
|
||||
direction.normalize();
|
||||
|
||||
this.center = this.position.clone();
|
||||
this.center.sub(direction);
|
||||
|
||||
this.target = this.position.clone();
|
||||
this.target.add(Tools.mul(direction,20));
|
||||
|
||||
|
||||
this.arrow = new THREE.Mesh(new THREE.Geometry(), new THREE.MeshLambertMaterial({color: 0x0000ff, side:THREE.BackSide}));
|
||||
|
||||
this.size = 0.4;
|
||||
|
||||
this.object3D = new THREE.Object3D();
|
||||
this.object3D.add(this.initExtremity());
|
||||
this.object3D.add(this.arrow);
|
||||
|
||||
this.fullArrow = false;
|
||||
|
||||
};
|
||||
ArrowCamera.prototype = Object.create(THREE.PerspectiveCamera.prototype);
|
||||
ArrowCamera.prototype.constructor = ArrowCamera;
|
||||
|
||||
ArrowCamera.prototype.check = function() {
|
||||
this.object3D.traverse(function(obj) {
|
||||
if (obj instanceof THREE.Mesh)
|
||||
obj.material.color.setHex(0x663366);
|
||||
});
|
||||
};
|
||||
|
||||
ArrowCamera.prototype.initExtremity = function() {
|
||||
var geometry = new THREE.Geometry();
|
||||
|
||||
var direction = this.target.clone();
|
||||
direction.sub(this.position);
|
||||
direction.normalize();
|
||||
|
||||
var left = Tools.cross(direction, this.up);
|
||||
var other = Tools.cross(direction, left);
|
||||
|
||||
|
||||
left.normalize();
|
||||
other.normalize();
|
||||
left = Tools.mul(left, this.size);
|
||||
other = Tools.mul(other, this.size);
|
||||
|
||||
geometry.vertices.push(Tools.sum( Tools.sum( this.position, left), other),
|
||||
Tools.diff(Tools.sum( this.position, other), left),
|
||||
Tools.diff(Tools.diff(this.position, left), other),
|
||||
Tools.sum( Tools.diff(this.position, other), left),
|
||||
Tools.sum(this.position, direction)
|
||||
);
|
||||
|
||||
geometry.faces.push(new THREE.Face3(0,2,1), // new THREE.Face3(0,2,1),
|
||||
new THREE.Face3(0,3,2), // new THREE.Face3(0,3,2)
|
||||
new THREE.Face3(4,1,2),
|
||||
new THREE.Face3(4,0,1),
|
||||
new THREE.Face3(4,3,0),
|
||||
new THREE.Face3(4,2,3)
|
||||
);
|
||||
|
||||
geometry.computeFaceNormals();
|
||||
|
||||
var material = new THREE.MeshLambertMaterial({
|
||||
color : 0x0000ff,
|
||||
transparent : true,
|
||||
opacity : 0.5,
|
||||
side: THREE.FrontSide
|
||||
});
|
||||
|
||||
this.mesh = new THREE.Mesh(geometry, material);
|
||||
return this.mesh;
|
||||
};
|
||||
|
||||
ArrowCamera.prototype.updateExtremity = function() {
|
||||
var direction = this.target.clone();
|
||||
direction.sub(this.position);
|
||||
direction.normalize();
|
||||
|
||||
var left = Tools.cross(direction, this.up);
|
||||
var other = Tools.cross(direction, left);
|
||||
|
||||
left.normalize();
|
||||
other.normalize();
|
||||
left = Tools.mul(left, this.size);
|
||||
other = Tools.mul(other, this.size);
|
||||
|
||||
this.mesh.geometry.vertices = [
|
||||
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)
|
||||
];
|
||||
|
||||
this.mesh.geometry.computeFaceNormals();
|
||||
this.mesh.geometry.verticesNeedUpdate = true;
|
||||
|
||||
};
|
||||
|
||||
ArrowCamera.prototype.setSize = function(size) {
|
||||
this.size = size;
|
||||
this.updateExtremity();
|
||||
};
|
||||
|
||||
// Update function
|
||||
ArrowCamera.prototype.update = function(mainCamera) {
|
||||
// Compute distance between center of camera and position
|
||||
dist = Tools.norm2(Tools.diff(mainCamera.position, this.center));
|
||||
|
||||
var low_bound = 1;
|
||||
var high_bound = 5;
|
||||
var new_value;
|
||||
|
||||
if (dist < low_bound) {
|
||||
new_value = 0;
|
||||
}
|
||||
else if (dist > high_bound) {
|
||||
new_value = 1;
|
||||
}
|
||||
else {
|
||||
new_value = (dist - low_bound)/(high_bound - low_bound);
|
||||
}
|
||||
|
||||
// Update opacity
|
||||
this.object3D.traverse(function(elt) {
|
||||
if (elt instanceof THREE.Mesh) {
|
||||
elt.material.transparent = new_value < 0.9;
|
||||
elt.material.opacity = new_value;
|
||||
|
||||
if (new_value < 0.1)
|
||||
elt.material.transparent = elt.visible = false;
|
||||
}
|
||||
});
|
||||
|
||||
this.regenerateArrow(mainCamera);
|
||||
};
|
||||
|
||||
ArrowCamera.prototype.regenerateArrow = function(mainCamera) {
|
||||
var i;
|
||||
var vertices = [];
|
||||
|
||||
// First point of curve
|
||||
var f0 = mainCamera.position.clone();
|
||||
f0.add(Tools.mul(Tools.sum(new THREE.Vector3(0,-0.5,0), Tools.diff(this.target, this.position).normalize()),2));
|
||||
|
||||
// Last point of curve
|
||||
var f1 = this.position.clone();
|
||||
|
||||
// Last derivative of curve
|
||||
var fp1 = Tools.diff(this.target, this.position);
|
||||
fp1.normalize();
|
||||
fp1.multiplyScalar(2);
|
||||
|
||||
// Camera direction
|
||||
var dir = Tools.diff(this.position, mainCamera.position);
|
||||
dir.normalize();
|
||||
|
||||
if (fp1.dot(dir) < -0.5) {
|
||||
// Regen polynom with better stuff
|
||||
// var new_dir = Tools.cross(Tools.diff(this.position, mainCamera.position).normalize(), mainCamera.up);
|
||||
// new_dir.multiplyScalar(new_dir.dot(fp1) < 0 ? 1 : -1);
|
||||
// new_dir.add(dir);
|
||||
// new_dir.add(dir);
|
||||
// new_dir.multiplyScalar(2);
|
||||
// f0.add(new_dir);
|
||||
|
||||
if (mainCamera.position.y > this.position.y) {
|
||||
f0.add(new THREE.Vector3(0,2,0));
|
||||
} else {
|
||||
f0.add(new THREE.Vector3(0,-2,0));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fp1.multiplyScalar(4);
|
||||
|
||||
var hermite = new Hermite.special.Polynom(f0, f1, fp1);
|
||||
|
||||
var up = this.up.clone();
|
||||
var point;
|
||||
var deriv;
|
||||
var limit = this.fullArrow ? 0.1 : 0.3;
|
||||
|
||||
// for (var i = this.fullArrow ? 0 : 0.5; i <= 1.001; i += 0.05) {
|
||||
for (i = 1; i > limit; i -= 0.1) {
|
||||
point = hermite.eval(i);
|
||||
deriv = hermite.prime(i);
|
||||
up.cross(deriv);
|
||||
up.cross(deriv);
|
||||
up.multiplyScalar(-1);
|
||||
up.normalize();
|
||||
|
||||
var coeff = this.size / 2;
|
||||
var left = Tools.cross(up, deriv); left.normalize(); left.multiplyScalar(coeff);
|
||||
var other = Tools.cross(deriv, left); other.normalize(); other.multiplyScalar(coeff);
|
||||
|
||||
vertices.push(
|
||||
Tools.sum(Tools.sum(point, left), other),
|
||||
Tools.sum(Tools.diff(point, left), other),
|
||||
Tools.diff(point, Tools.sum(other,left)),
|
||||
Tools.sum(Tools.diff(point, other), left)
|
||||
);
|
||||
}
|
||||
|
||||
this.arrow.geometry.vertices = vertices;
|
||||
|
||||
if (this.arrow.geometry.faces.length === 0) {
|
||||
var faces = [];
|
||||
|
||||
for (i = 0; i < vertices.length - 4; i+= 4) {
|
||||
faces.push(new THREE.Face3(i,i+1,i+5),new THREE.Face3(i,i+5,i+4),
|
||||
new THREE.Face3(i+1,i+2,i+6),new THREE.Face3(i+1,i+6,i+5),
|
||||
new THREE.Face3(i+2,i+3,i+7),new THREE.Face3(i+2,i+7,i+6),
|
||||
new THREE.Face3(i,i+7,i+3), new THREE.Face3(i,i+4,i+7));
|
||||
}
|
||||
|
||||
var len = vertices.length;
|
||||
faces.push(new THREE.Face3(len-4,len-3,len-2), new THREE.Face3(len-4,len-2,len-1));
|
||||
|
||||
// var max = 0;
|
||||
// for (var i = 0; i < faces.length; i++) {
|
||||
// max = Math.max(max, faces[i].a, faces[i].b, faces[i].c);
|
||||
// }
|
||||
// console.log(max + '/' + len);
|
||||
|
||||
|
||||
this.arrow.geometry.faces = faces;
|
||||
this.arrow.geometry.groupsNeedUpdate = true;
|
||||
this.arrow.geometry.elementsNeedUpdate = true;
|
||||
}
|
||||
|
||||
// this.arrow.geometry.mergeVertices();
|
||||
this.arrow.geometry.computeFaceNormals();
|
||||
// this.arrow.geometry.computeVertexNormals();
|
||||
this.arrow.geometry.computeBoundingSphere();
|
||||
|
||||
// this.arrow.geometry.vertices[0] = new THREE.Vector3(); // mainCamera.position.clone();
|
||||
// this.arrow.geometry.vertices[1] = this.position.clone();
|
||||
|
||||
this.arrow.geometry.dynamic = true;
|
||||
this.arrow.geometry.verticesNeedUpdate = true;
|
||||
// this.arrow.geometry.elementsNeedUpdate = true;
|
||||
// this.arrow.geometry.groupsNeedUpdate = true;
|
||||
this.arrow.geometry.normalsNeedUpdate = true;
|
||||
|
||||
};
|
||||
|
||||
// Look function
|
||||
ArrowCamera.prototype.look = function() {
|
||||
this.lookAt(this.target);
|
||||
};
|
||||
|
||||
ArrowCamera.prototype.addToScene = function(scene) {
|
||||
scene.add(this);
|
||||
scene.add(this.object3D);
|
||||
};
|
||||
|
||||
ArrowCamera.prototype.traverse = function(callback) {
|
||||
this.object3D.traverse(callback);
|
||||
};
|
||||
|
||||
ArrowCamera.prototype.containsObject = function(object) {
|
||||
return object.parent === this.object3D;
|
||||
};
|
||||
9
js/l3d/src/recommendations/FixedCamera.js
Normal file
9
js/l3d/src/recommendations/FixedCamera.js
Normal file
@@ -0,0 +1,9 @@
|
||||
// Initialization
|
||||
|
||||
// class camera extends THREE.PerspectiveCamera
|
||||
var FixedCamera = function(arg1, arg2, arg3, arg4, position, target) {
|
||||
ArrowCamera.apply(this, arguments);
|
||||
};
|
||||
FixedCamera.prototype = Object.create(ArrowCamera.prototype);
|
||||
FixedCamera.prototype.constructor = FixedCamera;
|
||||
|
||||
195
js/l3d/src/recommendations/OldFixedCamera.js
Normal file
195
js/l3d/src/recommendations/OldFixedCamera.js
Normal file
@@ -0,0 +1,195 @@
|
||||
// Initialization
|
||||
|
||||
// class camera extends THREE.PerspectiveCamera
|
||||
var OldFixedCamera = function(arg1, arg2, arg3, arg4, position, target) {
|
||||
THREE.PerspectiveCamera.apply(this, arguments);
|
||||
|
||||
// Set Position
|
||||
if (position === undefined) {
|
||||
this.position = new THREE.Vector3(0,0,5);
|
||||
} else {
|
||||
this.position.x = position.x;
|
||||
this.position.y = position.y;
|
||||
this.position.z = position.z;
|
||||
}
|
||||
|
||||
if (target === undefined)
|
||||
target = new THREE.Vector3(0,0,0);
|
||||
|
||||
var direction = target.clone();
|
||||
direction.sub(this.position);
|
||||
direction.normalize();
|
||||
|
||||
this.target = this.position.clone();
|
||||
this.target.add(Tools.mul(direction,10));
|
||||
// this.up = new THREE.Vector3(0,0,1);
|
||||
|
||||
// Compute corners
|
||||
|
||||
// Create the mesh to draw
|
||||
|
||||
var geometry = new THREE.Geometry();
|
||||
|
||||
var left = Tools.cross(direction, this.up);
|
||||
var other = Tools.cross(direction, left);
|
||||
left.normalize();
|
||||
other.normalize();
|
||||
left = Tools.mul(left, 1);
|
||||
other = Tools.mul(other, 1);
|
||||
|
||||
geometry.vertices.push(Tools.sum(Tools.sum(this.position, left), other),
|
||||
Tools.diff(Tools.sum(this.position, other),left),
|
||||
Tools.diff(Tools.diff(this.position, left),other),
|
||||
Tools.sum(Tools.diff(this.position, other), left)
|
||||
);
|
||||
|
||||
geometry.faces.push(new THREE.Face3(0,1,2), // new THREE.Face3(0,2,1),
|
||||
new THREE.Face3(0,2,3) // new THREE.Face3(0,3,2)
|
||||
);
|
||||
|
||||
(function(self, direction, left, other) {
|
||||
var material = new THREE.LineBasicMaterial({ color: '0x000000'});
|
||||
var geometry = new THREE.Geometry();
|
||||
var tmp_direction = Tools.mul(direction, -2);
|
||||
var target = Tools.sum(self.position, tmp_direction);
|
||||
// geometry.vertices.push(self.position, target);
|
||||
geometry.vertices.push(
|
||||
Tools.sum(Tools.sum(self.position, left), other),
|
||||
Tools.diff(Tools.sum(self.position, other),left),
|
||||
Tools.diff(Tools.diff(self.position, left),other),
|
||||
Tools.sum(Tools.diff(self.position, other), left),
|
||||
Tools.sum(Tools.sum(self.position, left), other),
|
||||
Tools.sum(Tools.diff(self.position, other), left),
|
||||
|
||||
Tools.sum(self.position, tmp_direction),
|
||||
Tools.sum(Tools.sum(self.position, left), other),
|
||||
|
||||
Tools.sum(self.position, tmp_direction),
|
||||
Tools.diff(Tools.sum(self.position, other),left),
|
||||
|
||||
Tools.sum(self.position, tmp_direction),
|
||||
Tools.diff(Tools.diff(self.position, left),other),
|
||||
|
||||
Tools.sum(self.position, tmp_direction),
|
||||
Tools.sum(Tools.diff(self.position, other), left)
|
||||
);
|
||||
|
||||
self.line = new THREE.Line(geometry, material);
|
||||
})(this, direction, left, other);
|
||||
|
||||
|
||||
var material = new THREE.MeshBasicMaterial({
|
||||
color : 0x0000ff,
|
||||
transparent : true,
|
||||
opacity : 1,
|
||||
side: THREE.DoubleSide
|
||||
});
|
||||
|
||||
this.mesh = new THREE.Mesh(geometry, material);
|
||||
this.mesh.raycastable = true;
|
||||
};
|
||||
OldFixedCamera.prototype = Object.create(THREE.PerspectiveCamera.prototype);
|
||||
OldFixedCamera.prototype.constructor = OldFixedCamera;
|
||||
|
||||
OldFixedCamera.prototype.check = function() {
|
||||
this.mesh.material.color.setHex(0x663366);
|
||||
};
|
||||
|
||||
// Update function
|
||||
OldFixedCamera.prototype.update = function(position) {
|
||||
// Compute distance between center of camera and position
|
||||
dist = Tools.norm2(Tools.diff(position.position, this.position));
|
||||
|
||||
var low_bound = 1;
|
||||
var high_bound = 5;
|
||||
var new_value;
|
||||
var max_value = 0.5;
|
||||
|
||||
if (dist < low_bound)
|
||||
new_value = 0;
|
||||
else if (dist > high_bound)
|
||||
new_value = max_value;
|
||||
else
|
||||
new_value = max_value * (dist - low_bound)/(high_bound - low_bound);
|
||||
|
||||
this.mesh.material.transparent = new_value < 0.9;
|
||||
this.mesh.material.opacity = new_value;
|
||||
|
||||
if (new_value < 0.1)
|
||||
this.mesh.material.transparent = this.mesh.visible = false;
|
||||
};
|
||||
|
||||
// Look function
|
||||
OldFixedCamera.prototype.look = function() {
|
||||
this.lookAt(this.target);
|
||||
};
|
||||
|
||||
OldFixedCamera.prototype.addToScene = function(scene) {
|
||||
scene.add(this);
|
||||
scene.add(this.mesh);
|
||||
scene.add(this.line);
|
||||
};
|
||||
|
||||
OldFixedCamera.prototype.traverse = function(callback) {
|
||||
callback(this.mesh);
|
||||
callback(this.line);
|
||||
};
|
||||
|
||||
OldFixedCamera.prototype.containsObject = function(object) {
|
||||
return object === this.mesh;
|
||||
};
|
||||
|
||||
OldFixedCamera.prototype.setSize = function(size) {
|
||||
|
||||
var direction = this.target.clone();
|
||||
direction.sub(this.position);
|
||||
direction.normalize();
|
||||
|
||||
var left = Tools.cross(direction, this.up);
|
||||
var other = Tools.cross(direction, left);
|
||||
left.normalize();
|
||||
other.normalize();
|
||||
left = Tools.mul(left, size);
|
||||
other = Tools.mul(other, size);
|
||||
|
||||
this.mesh.geometry.vertices = [
|
||||
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)
|
||||
];
|
||||
|
||||
this.mesh.geometry.verticesNeedUpdate = true;
|
||||
|
||||
(function(self, direction, left, other, size) {
|
||||
|
||||
var tmp_direction = Tools.mul(direction, -2 * size);
|
||||
var target = Tools.sum(self.position, tmp_direction);
|
||||
|
||||
var vertices = [
|
||||
Tools.sum(Tools.sum(self.position, left), other),
|
||||
Tools.diff(Tools.sum(self.position, other),left),
|
||||
Tools.diff(Tools.diff(self.position, left),other),
|
||||
Tools.sum(Tools.diff(self.position, other), left),
|
||||
Tools.sum(Tools.sum(self.position, left), other),
|
||||
Tools.sum(Tools.diff(self.position, other), left),
|
||||
|
||||
Tools.sum(self.position, tmp_direction),
|
||||
Tools.sum(Tools.sum(self.position, left), other),
|
||||
|
||||
Tools.sum(self.position, tmp_direction),
|
||||
Tools.diff(Tools.sum(self.position, other),left),
|
||||
|
||||
Tools.sum(self.position, tmp_direction),
|
||||
Tools.diff(Tools.diff(self.position, left),other),
|
||||
|
||||
Tools.sum(self.position, tmp_direction),
|
||||
Tools.sum(Tools.diff(self.position, other), left)
|
||||
];
|
||||
|
||||
self.line.geometry.vertices = vertices;
|
||||
self.line.geometry.verticesNeedUpdate = true;
|
||||
|
||||
})(this, direction, left, other, size);
|
||||
|
||||
};
|
||||
181
js/l3d/src/recommendations/ReverseCamera.js
Normal file
181
js/l3d/src/recommendations/ReverseCamera.js
Normal file
@@ -0,0 +1,181 @@
|
||||
// Initialization
|
||||
|
||||
// class camera extends THREE.PerspectiveCamera
|
||||
var ReverseCamera = function(arg1, arg2, arg3, arg4, position, target) {
|
||||
ArrowCamera.apply(this, arguments);
|
||||
};
|
||||
ReverseCamera.prototype = Object.create(ArrowCamera.prototype);
|
||||
ReverseCamera.prototype.constructor = ReverseCamera;
|
||||
|
||||
// Overload init
|
||||
ReverseCamera.prototype.initExtremity = function() {
|
||||
var geometry = new THREE.Geometry();
|
||||
|
||||
var direction = this.target.clone();
|
||||
direction.sub(this.position);
|
||||
direction.normalize();
|
||||
|
||||
var left = Tools.cross(direction, this.up);
|
||||
var other = Tools.cross(direction, left);
|
||||
|
||||
left.normalize();
|
||||
other.normalize();
|
||||
left = Tools.mul(left, this.size / 2 );
|
||||
other = Tools.mul(other, this.size / 2);
|
||||
|
||||
var pyramidCenter = Tools.diff(this.position, Tools.mul(direction,0.25));
|
||||
geometry.vertices.push(
|
||||
Tools.sum( Tools.sum( this.position, left), other),
|
||||
Tools.diff(Tools.sum( this.position, other), left),
|
||||
Tools.diff(Tools.diff(this.position, left), other),
|
||||
Tools.sum( Tools.diff(this.position, other), left),
|
||||
|
||||
Tools.sum( Tools.sum( this.position, left), other),
|
||||
Tools.diff(Tools.sum( this.position, other), left),
|
||||
Tools.diff(Tools.diff(this.position, left), other),
|
||||
Tools.sum( Tools.diff(this.position, other), left)
|
||||
// Tools.diff(this.position, direction)
|
||||
);
|
||||
|
||||
var lambda = 0.6;
|
||||
for (var i = 0; i < 4; i++)
|
||||
geometry.vertices[i] = Tools.mul(Tools.diff(geometry.vertices[i], Tools.mul(pyramidCenter,lambda)), 1/(1-lambda));
|
||||
|
||||
|
||||
geometry.faces.push(new THREE.Face3(2,0,1), // new THREE.Face3(0,2,1),
|
||||
new THREE.Face3(3,0,2), // new THREE.Face3(0,3,2)
|
||||
|
||||
new THREE.Face3(1,0,4),
|
||||
new THREE.Face3(1,4,5),
|
||||
|
||||
new THREE.Face3(2,1,5),
|
||||
new THREE.Face3(2,5,6),
|
||||
|
||||
new THREE.Face3(7,2,6),
|
||||
new THREE.Face3(7,3,2),
|
||||
|
||||
new THREE.Face3(3,7,4),
|
||||
new THREE.Face3(3,4,0)
|
||||
|
||||
);
|
||||
|
||||
geometry.computeFaceNormals();
|
||||
|
||||
var material = new THREE.MeshLambertMaterial({
|
||||
color : 0x0000ff,
|
||||
transparent : true,
|
||||
opacity : 0.5,
|
||||
side: THREE.FrontSide
|
||||
});
|
||||
|
||||
this.mesh = new THREE.Mesh(geometry, material);
|
||||
return this.mesh;
|
||||
|
||||
};
|
||||
|
||||
ReverseCamera.prototype.regenerateArrow = function(mainCamera) {
|
||||
var i;
|
||||
var vertices = [];
|
||||
|
||||
// First point of curve
|
||||
var f0 = mainCamera.position.clone();
|
||||
f0.add(Tools.mul(Tools.sum(new THREE.Vector3(0,-0.5,0), Tools.diff(this.target, this.position).normalize()),2));
|
||||
|
||||
// Last point of curve
|
||||
var f1 = this.position.clone();
|
||||
|
||||
// Last derivative of curve
|
||||
var fp1 = Tools.diff(this.target, this.position);
|
||||
fp1.normalize();
|
||||
fp1.multiplyScalar(2);
|
||||
|
||||
// Camera direction
|
||||
var dir = Tools.diff(this.position, mainCamera.position);
|
||||
dir.normalize();
|
||||
|
||||
if (fp1.dot(dir) < -0.5) {
|
||||
// Regen polynom with better stuff
|
||||
// var new_dir = Tools.cross(Tools.diff(this.position, mainCamera.position).normalize(), mainCamera.up);
|
||||
// new_dir.multiplyScalar(new_dir.dot(fp1) < 0 ? 1 : -1);
|
||||
// new_dir.add(dir);
|
||||
// new_dir.add(dir);
|
||||
// new_dir.multiplyScalar(2);
|
||||
// f0.add(new_dir);
|
||||
|
||||
if (mainCamera.position.y > this.position.y) {
|
||||
f0.add(new THREE.Vector3(0,2,0));
|
||||
} else {
|
||||
f0.add(new THREE.Vector3(0,-2,0));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fp1.multiplyScalar(4);
|
||||
|
||||
var hermite = new Hermite.special.Polynom(f0, f1, fp1);
|
||||
|
||||
var up = this.up.clone();
|
||||
var point;
|
||||
var deriv;
|
||||
var limit = this.fullArrow ? 0.1 : 0.3;
|
||||
|
||||
// for (var i = this.fullArrow ? 0 : 0.5; i <= 1.001; i += 0.05) {
|
||||
for (i = 1; i > limit; i -= 0.1) {
|
||||
point = hermite.eval(i);
|
||||
deriv = hermite.prime(i);
|
||||
up.cross(deriv);
|
||||
up.cross(deriv);
|
||||
up.multiplyScalar(-1);
|
||||
up.normalize();
|
||||
|
||||
var coeff = i * i * this.size / 2;
|
||||
var left = Tools.cross(up, deriv); left.normalize(); left.multiplyScalar(coeff);
|
||||
var other = Tools.cross(deriv, left); other.normalize(); other.multiplyScalar(coeff);
|
||||
|
||||
vertices.push(
|
||||
Tools.sum(Tools.sum(point, left), other),
|
||||
Tools.sum(Tools.diff(point, left), other),
|
||||
Tools.diff(point, Tools.sum(other,left)),
|
||||
Tools.sum(Tools.diff(point, other), left)
|
||||
);
|
||||
}
|
||||
|
||||
this.arrow.geometry.vertices = vertices;
|
||||
|
||||
if (this.arrow.geometry.faces.length === 0) {
|
||||
var faces = [];
|
||||
|
||||
for (i = 0; i < vertices.length - 4; i+= 4) {
|
||||
faces.push(new THREE.Face3(i,i+1,i+5),new THREE.Face3(i,i+5,i+4),
|
||||
new THREE.Face3(i+1,i+2,i+6),new THREE.Face3(i+1,i+6,i+5),
|
||||
new THREE.Face3(i+2,i+3,i+7),new THREE.Face3(i+2,i+7,i+6),
|
||||
new THREE.Face3(i,i+7,i+3), new THREE.Face3(i,i+4,i+7));
|
||||
}
|
||||
|
||||
var len = vertices.length;
|
||||
faces.push(new THREE.Face3(len-4,len-3,len-2), new THREE.Face3(len-4,len-2,len-1));
|
||||
|
||||
var max = 0;
|
||||
for (i = 0; i < faces.length; i++) {
|
||||
max = Math.max(max, faces[i].a, faces[i].b, faces[i].c);
|
||||
}
|
||||
console.log(max + '/' + len);
|
||||
|
||||
|
||||
this.arrow.geometry.faces = faces;
|
||||
this.arrow.geometry.groupsNeedUpdate = true;
|
||||
this.arrow.geometry.elementsNeedUpdate = true;
|
||||
}
|
||||
|
||||
// this.arrow.geometry.mergeVertices();
|
||||
this.arrow.geometry.computeFaceNormals();
|
||||
// this.arrow.geometry.computeVertexNormals();
|
||||
this.arrow.geometry.computeBoundingSphere();
|
||||
|
||||
// this.arrow.geometry.vertices[0] = new THREE.Vector3(); // mainCamera.position.clone();
|
||||
// this.arrow.geometry.vertices[1] = this.position.clone();
|
||||
|
||||
this.arrow.geometry.dynamic = true;
|
||||
this.arrow.geometry.verticesNeedUpdate = true;
|
||||
|
||||
};
|
||||
736
js/l3d/src/scenes/initScene.js
Normal file
736
js/l3d/src/scenes/initScene.js
Normal file
@@ -0,0 +1,736 @@
|
||||
// Define RecommendedCamera if not defined
|
||||
var RecommendedCamera = RecommendedCamera || FixedCamera;
|
||||
|
||||
function addLight(scene) {
|
||||
var directional_light = new THREE.DirectionalLight(0xdddddd);
|
||||
directional_light.position.set(1, 2.5, 1).normalize();
|
||||
directional_light.castShadow = false;
|
||||
scene.add(directional_light);
|
||||
|
||||
var ambient_light = new THREE.AmbientLight(0x555555);
|
||||
scene.add(ambient_light);
|
||||
}
|
||||
|
||||
function initPeachCastle(scene, collidableObjects, camera) {
|
||||
|
||||
var loader = new ProgressiveLoaderGeometry(
|
||||
'/static/data/castle/princess peaches castle (outside).obj',
|
||||
scene,
|
||||
null,
|
||||
function(object) {
|
||||
object.raycastable = true;
|
||||
if (object.material.name === 'Material.103_princess_peaches_cast') {
|
||||
THREEx.Transparency.push(object);
|
||||
} else if (object.material.name === 'Material.136_princess_peaches_cast' ||
|
||||
object.material.name === 'Material.135_princess_peaches_cast') {
|
||||
THREEx.Transparency.push(object);
|
||||
object.material.opacity = 0.5;
|
||||
object.raycastable = false;
|
||||
object.material.side = THREE.FrontSide;
|
||||
}
|
||||
}
|
||||
);
|
||||
loader.load();
|
||||
|
||||
collidableObjects.push(loader.obj);
|
||||
loader.obj.raycastable = true;
|
||||
}
|
||||
|
||||
function resetPeachElements() {
|
||||
return {
|
||||
position: new THREE.Vector3(0.24120226734236713,0.2009624547018851,-0.5998422840047036),
|
||||
target: new THREE.Vector3(0.24120226734232672,0.20096245470190008,-40.5998422840047)
|
||||
};
|
||||
}
|
||||
|
||||
function initPeach(camera, scene, coins) {
|
||||
addLight(scene);
|
||||
|
||||
var collidableObjects = [];
|
||||
initPeachCastle(scene, collidableObjects, camera);
|
||||
|
||||
camera.resetElements = resetPeachElements();
|
||||
camera.collidableObjects = collidableObjects;
|
||||
|
||||
camera.speed = 0.001;
|
||||
camera.reset();
|
||||
camera.save();
|
||||
|
||||
scene.add(camera);
|
||||
|
||||
Coin.init(0.001);
|
||||
var otherCams = [];
|
||||
var cameras = new CameraContainer(camera, otherCams);
|
||||
|
||||
return cameras;
|
||||
}
|
||||
|
||||
function initZeldaScene(scene, collidableObjects, loader) {
|
||||
// Create loader if not already done
|
||||
if (loader === undefined) {
|
||||
loader = new THREE.OBJMTLLoader();
|
||||
}
|
||||
|
||||
loader.load(
|
||||
'/static/data/zelda/Island.obj',
|
||||
'/static/data/zelda/Island.mtl',
|
||||
function ( object ) {
|
||||
collidableObjects.push(object);
|
||||
object.scale.set(0.01,0.01,0.01);
|
||||
object.traverse(function (object) {
|
||||
if (object instanceof THREE.Mesh) {
|
||||
object.geometry.mergeVertices();
|
||||
object.geometry.computeVertexNormals();
|
||||
object.material.side = THREE.DoubleSide;
|
||||
object.raycastable = true;
|
||||
if (object.material.name === 'm0') {
|
||||
THREEx.Transparency.push(object);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
function createPeachCameras(width, height) {
|
||||
var cams = [];
|
||||
|
||||
var createCamera = function(position, target) {
|
||||
return new RecommendedCamera(
|
||||
50,
|
||||
width / height,
|
||||
1,
|
||||
100000,
|
||||
position,
|
||||
target
|
||||
);
|
||||
};
|
||||
|
||||
cams.push(createCamera(
|
||||
new THREE.Vector3(-3.349895207953063, 5.148106346852601, 0.3365943929701533),
|
||||
new THREE.Vector3(13.114421714865292, -7.783476327687569, -33.74713248359852)
|
||||
));
|
||||
|
||||
cams.push(createCamera(
|
||||
new THREE.Vector3(4.659399030971226, 1.018674883050052597, -2.578139604982815),
|
||||
new THREE.Vector3(-16.08800293200113, -28.8795632312717, -19.165379404919797)
|
||||
));
|
||||
|
||||
cams.push(createCamera(
|
||||
new THREE.Vector3(2.625389073616235, 1.2252620948239699, -4.818718135555419),
|
||||
new THREE.Vector3(-19.756833131355208, -16.20027570329664, -33.02132017177813)
|
||||
));ader = new THREE.MTLLoader('/static/data/bobomb/');
|
||||
// loader.
|
||||
|
||||
// cams.push(createCamera(
|
||||
// new THREE.Vector3(1.3304975149911331, 0.4836093721106701, -8.60618907952783),
|
||||
// new THREE.Vector3(-1.7713635815431914, 6.271997833695163, -48.06341930106774)
|
||||
// ));
|
||||
|
||||
// cams.push(createCamera(
|
||||
// new THREE.Vector3(1.2976081760482443, 1.1520399813234647, -10.258148122402845),
|
||||
// new THREE.Vector3(-26.00651734173549, -9.19681009597505, -37.596510029925945)
|
||||
// ));
|
||||
|
||||
cams.push(createCamera(
|
||||
new THREE.Vector3(0.15727187830660858, 2.7251137440572855, -5.84333603646124),
|
||||
new THREE.Vector3(19.33738702531091, -13.614383891308975, -36.91010284556961)
|
||||
));
|
||||
|
||||
cams.push(createCamera(
|
||||
new THREE.Vector3(-3.912436457101955,1.4571795397310319,-7.361700012948173),
|
||||
new THREE.Vector3(26.60153755572943,-12.280244389383581,-29.274722938506393)
|
||||
));
|
||||
|
||||
cams.push(createCamera(
|
||||
new THREE.Vector3(4.734058048040269,0.9171350442568073,0.12604632828978296),
|
||||
new THREE.Vector3(25.163187055614348,-27.08137327531798,-19.842284094421995)
|
||||
));
|
||||
|
||||
cams.forEach(function(cam) {cam.setSize(0.2);});
|
||||
|
||||
return cams;
|
||||
}
|
||||
|
||||
function initBobombScene(scene, collidableObjects, camera) {
|
||||
|
||||
var loader = new ProgressiveLoaderGeometry(
|
||||
'/static/data/bobomb/bobomb battlefeild.obj',
|
||||
scene,
|
||||
null,
|
||||
function(object) {
|
||||
object.raycastable = true;
|
||||
if (object.material.name === 'Material.071_574B138E_c.bmp' ||
|
||||
object.material.name === 'Material.070_41A41EE3_c.bmp') {
|
||||
THREEx.Transparency.push(object);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
loader.load();
|
||||
var theta = 0.27;
|
||||
loader.obj.rotation.y = Math.PI - theta;
|
||||
|
||||
loader.obj.up = new THREE.Vector3(0,0,1);
|
||||
collidableObjects.push(loader.obj);
|
||||
|
||||
}
|
||||
|
||||
function resetBobombElements() {
|
||||
return {
|
||||
position: new THREE.Vector3(38.115627509754646,10.829803024792419,-19.862035691341315),
|
||||
target: new THREE.Vector3(-1.4518898576752122,5.048214777643772,-18.869661407832535)
|
||||
};
|
||||
}
|
||||
|
||||
function createBobombCoins() {
|
||||
var coins = [];
|
||||
|
||||
coins.push(
|
||||
new Coin(-1.6204001515660262,12.245208850063094,-24.871861611322934),
|
||||
new Coin(23.509767766131876,13.6929075780209,-6.1716274892265615),
|
||||
new Coin(34.797219873325524,13.088500612704706,-2.1784858128827413),
|
||||
new Coin(-23.255456493345882,15.763954882327724,-11.08029248078497),
|
||||
new Coin(-7.238094745133173,12.95460420281499,-3.1009487490121885),
|
||||
new Coin(-17.10578612221326,24.17871082944758,-11.574224169812915),
|
||||
new Coin(-12.418656949661646,17.09780294217035,32.472022253887665),
|
||||
new Coin(7.132802719121488,8.802400710545713,22.258165594421055)
|
||||
);
|
||||
|
||||
return coins;
|
||||
}
|
||||
|
||||
function createBobombCameras(width, height) {
|
||||
var cams = [];
|
||||
|
||||
var createCamera = function(position, target) {
|
||||
return new RecommendedCamera(
|
||||
50,
|
||||
width / height,
|
||||
1,
|
||||
100000,
|
||||
position,
|
||||
target
|
||||
);
|
||||
};
|
||||
|
||||
cams.push(
|
||||
createCamera(
|
||||
new THREE.Vector3(37.24445046448742,17.56004329173052,-13.432945825465112),
|
||||
new THREE.Vector3(15.446296842638255,0.7142524861838169,15.568085721947512)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(-24.10987782946019,26.75997424452833,-24.7814217620827),
|
||||
new THREE.Vector3(-13.724964120740987,14.939165978074758,11.993869660150779)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(7.162458619916293,18.414234017280627,-10.871480453809644),
|
||||
new THREE.Vector3(-27.47061192698706,3.9199238382137196,2.9294396939998144)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(19.741775033926334,14.132046557015727,-25.338452829449857),
|
||||
new THREE.Vector3(-18.0898892760213,1.5191520612050162,-28.449733590966297)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(-13.484471970922971,20.25938194278451,-30.850247430073622),
|
||||
new THREE.Vector3(-42.04654352929252,-7.608886431102082,-28.099304657929874)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(23.58849177613168,18.628351213754488,31.516769692916675),
|
||||
new THREE.Vector3(8.319765065757787,-0.5486703304136178,-0.09189730426033549)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(5.068708131530766,11.201320390433953,9.77462743108436),
|
||||
new THREE.Vector3(9.20744154720096,3.8549750522404134,48.87580511010085)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(4.18086580540298,16.54831275414988,29.96253548469186),
|
||||
new THREE.Vector3(-17.059296481928556,3.408610856102113,-1.2817238286325505)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(-44.56340663230823,22.567957426093283,14.856920056929788),
|
||||
new THREE.Vector3(-20.052660826451827,7.556450599683849,42.67558290835663)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(11.29580093093769,15.03666008708929,31.377195488571406),
|
||||
new THREE.Vector3(-28.288314738873957,13.648654387264967,25.794075678265735)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(28.438969076366728,18.888756501203087,26.694456000440766),
|
||||
new THREE.Vector3(-5.369166248035665,2.54925886583683,12.909289954623416)
|
||||
)
|
||||
);
|
||||
|
||||
return cams;
|
||||
|
||||
}
|
||||
|
||||
function initBobomb(camera, scene, coins) {
|
||||
addLight(scene);
|
||||
|
||||
var collidableObjects = [];
|
||||
initBobombScene(scene, collidableObjects, camera);
|
||||
|
||||
camera.resetElements = resetBobombElements();
|
||||
camera.collidableObjects = collidableObjects;
|
||||
|
||||
camera.speed = 0.005;
|
||||
camera.reset();
|
||||
camera.save();
|
||||
|
||||
scene.add(camera);
|
||||
|
||||
Coin.init();
|
||||
var tmp = createBobombCoins();
|
||||
|
||||
for (var i in tmp) {
|
||||
coins.push(tmp[i]);
|
||||
}
|
||||
|
||||
var otherCams = createBobombCameras(container_size.width(), container_size.height());
|
||||
var cameras = new CameraContainer(camera, otherCams);
|
||||
|
||||
otherCams.forEach(function(cam) {cam.addToScene(scene);});
|
||||
|
||||
setTimeout(function() { coins.forEach(function(coin) { coin.addToScene(scene); });}, 1000);
|
||||
|
||||
return cameras;
|
||||
}
|
||||
|
||||
function initWhompScene(scene, collidableObjects, camera) {
|
||||
|
||||
var loader = new ProgressiveLoaderGeometry(
|
||||
'/static/data/whomp/Whomps Fortress.obj',
|
||||
scene,
|
||||
null,
|
||||
function(object) {
|
||||
object.raycastable = true;
|
||||
if (object.material.name === 'Shape_088' ||
|
||||
object.material.name === 'Shape_089') {
|
||||
object.raycastable = false;
|
||||
THREEx.Transparency.push(object);
|
||||
} else if (object.material.name === 'Shape_113') {
|
||||
THREEx.Transparency.push(object);
|
||||
object.material.opacity = 0.5;
|
||||
} else if (object.material.name === 'Shape_076' ||
|
||||
object.material.name === 'Shape_098' ||
|
||||
object.material.name === 'Shape_092') {
|
||||
object.visible = false;
|
||||
}
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
loader.load();
|
||||
|
||||
loader.obj.rotation.x = -Math.PI/2;
|
||||
loader.obj.rotation.z = Math.PI/2;
|
||||
loader.obj.scale.set(0.1,0.1,0.1);
|
||||
|
||||
// loader.getCamera = function() {
|
||||
// var ret = loader.camera.toList();
|
||||
// ret[0][0] *= 10;
|
||||
// ret[0][1] *= 10;
|
||||
// ret[0][2] *= 10;
|
||||
|
||||
// ret[1][0] *= 10;
|
||||
// ret[1][1] *= 10;
|
||||
// ret[1][2] *= 10;
|
||||
|
||||
// // Planes
|
||||
// for (var i = 2; i < ret.length; i++) {
|
||||
|
||||
// ret[i][3] *= 10;
|
||||
|
||||
// }
|
||||
|
||||
// return ret;
|
||||
// };
|
||||
|
||||
collidableObjects.push(loader.obj);
|
||||
loader.obj.raycastable = true;
|
||||
}
|
||||
|
||||
function createWhompCameras(width, height) {
|
||||
var cams = [];
|
||||
|
||||
var createCamera = function(position, target) {
|
||||
return new RecommendedCamera(
|
||||
50,
|
||||
width / height,
|
||||
1,
|
||||
100000,
|
||||
position,
|
||||
target
|
||||
);
|
||||
};
|
||||
|
||||
cams.push(
|
||||
createCamera(
|
||||
new THREE.Vector3(-5.4336754204569345,3.1392444908865986,-2.5523620854280967),
|
||||
new THREE.Vector3(-5.284005453263061, 2.9591143163290674, 1.440776031533807)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(-6.1753139246999424,3.1460450777755153, 8.89776989593906),
|
||||
new THREE.Vector3(-2.7026837603414037,3.365743354536376, 6.924809579871983)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(-5.4975217973818246,7.726911253355844, 2.805487210952553),
|
||||
new THREE.Vector3(-2.262483559754942, 5.4847179687372005, 2.0933798626524435)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(767.5978415761134, 3.641765617950047, -6.734909128840316),
|
||||
new THREE.Vector3(800.1643232028776, 2.192334600043356, -3.0210038861375168)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(-4.521868295112849, 4.598285007581405, -7.186164895937964),
|
||||
new THREE.Vector3(-1.2890361546656827,2.964335244044779, -5.489401941978159)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(7.669185389234946,3.470810613964853,-7.254996785427332),
|
||||
new THREE.Vector3(11.103044107444248,-8.414196017364398,30.78386796730468)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(-5.00642950829277,7.5887626003253095,-5.785306379113327),
|
||||
new THREE.Vector3(30.922081744183423,1.5447833064028265,10.725671589357493)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(10.73348160390988,7.384861575888838,-5.156956944727774),
|
||||
new THREE.Vector3(-17.904597948771446,1.3408822819663548,22.107135078094704)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(6.571383420547652,6.592495890455599,8.530692470963302),
|
||||
new THREE.Vector3(-17.04673536396069,6.525278678835147,-23.752119471730232)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(-2.658378348430724,9.934059833300438,4.832483419920441),
|
||||
new THREE.Vector3(31.687909225501116,1.921420479172772,-14.038927244612823)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(0.32263636932421563,14.77110426329107,-4.846281929349468),
|
||||
new THREE.Vector3(13.444429209246985,-2.688018079059324,28.664874417470223)
|
||||
)
|
||||
|
||||
);
|
||||
|
||||
cams.forEach(function(cam) {cam.setSize(0.2);});
|
||||
return cams;
|
||||
}
|
||||
|
||||
function createWhompCoins() {
|
||||
return [
|
||||
new Coin(-5.529176900669821,2.886514571524507,4.127968972716147),
|
||||
new Coin(-3.336263561768484,9.341710952326468,1.0230063543998414),
|
||||
new Coin(1.985057515492925,12.151756532082196,1.3355674703297925),
|
||||
new Coin(8.100383890535953,4.6489182333624335,1.9132972963126775),
|
||||
new Coin(0.6049016864458896,6.2498603432959584,3.6272087520336264),
|
||||
new Coin(-1.4497656612870164,6.263594147452652,-4.0488101538390694),
|
||||
new Coin(6.753883218882444,2.019245026490682,-7.001046531863012),
|
||||
new Coin(3.4354286209455246,3.487313067990168,-4.091947594995703)
|
||||
];
|
||||
}
|
||||
|
||||
function resetWhompElements() {
|
||||
return {
|
||||
position : new THREE.Vector3(-6.725817925071645,1.4993570618328055,-10.356480813212423),
|
||||
target : new THREE.Vector3(-4.8541705829784604,1.3192268872752742,-6.825972443720941)
|
||||
};
|
||||
}
|
||||
|
||||
function initWhomp(camera, scene, coins) {
|
||||
addLight(scene);
|
||||
|
||||
var collidableObjects = [];
|
||||
initWhompScene(scene, collidableObjects, camera);
|
||||
|
||||
camera.resetElements = resetWhompElements();
|
||||
camera.collidableObjects = collidableObjects;
|
||||
|
||||
camera.speed = 0.002;
|
||||
camera.reset();
|
||||
camera.save();
|
||||
|
||||
scene.add(camera);
|
||||
|
||||
Coin.init(0.002);
|
||||
var tmp = createWhompCoins();
|
||||
|
||||
for (var i in tmp) {
|
||||
coins.push(tmp[i]);
|
||||
}
|
||||
|
||||
var otherCams = createWhompCameras(container_size.width(), container_size.height());
|
||||
var cameras = new CameraContainer(camera, otherCams);
|
||||
|
||||
otherCams.forEach(function(cam) {cam.addToScene(scene);});
|
||||
|
||||
setTimeout(function() { coins.forEach(function(coin) { coin.addToScene(scene); });}, 1000);
|
||||
|
||||
return cameras;
|
||||
}
|
||||
|
||||
function initMountainScene(scene, collidableObjects, camera) {
|
||||
|
||||
var loader = new ProgressiveLoaderGeometry(
|
||||
'/static/data/mountain/coocoolmountain.obj',
|
||||
scene,
|
||||
null,
|
||||
function(object) {
|
||||
// object.rotation.x = -Math.PI/2;
|
||||
// object.rotation.z = Math.PI/2;
|
||||
object.raycastable = true;
|
||||
if (object.material.name === 'Material.070_13F025D5_c2.png' ||
|
||||
object.material.name === 'Material.068_5972FC88_c.bmp' ||
|
||||
object.material.name === 'Material.073_76F611AD_c.bmp' ||
|
||||
object.material.name === 'Material.071_76F611AD_c.bmp' ||
|
||||
object.material.name === 'Material.072_1723CCC7_c.bmp' ||
|
||||
object.material.name === 'Material.069_78B64DC7_c.bmp' ||
|
||||
object.material.name === 'Material.070_13F025D5_c.bmp' ||
|
||||
object.material.name === 'Material.078_3165B23A_c.bmp' ||
|
||||
object.material.name === 'Material.067_1723CCC7_c.bmp' ||
|
||||
object.material.name === 'Material.066_36DB292F_c.bmp') {
|
||||
THREEx.Transparency.push(object);
|
||||
} else if (object.material.name === 'Material.082_6DAF90F6_c.bmp') {
|
||||
THREEx.Transparency.push(object);
|
||||
object.material.opacity = 0.5;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
loader.load();
|
||||
collidableObjects.push(loader.obj);
|
||||
}
|
||||
|
||||
function createMountainCoins() {
|
||||
return [
|
||||
new Coin(-18.766484229298513,-6.174512332611151,16.379061147364553),
|
||||
new Coin(-22.48878786991581,-17.698282433679474,1.6030258853572397),
|
||||
new Coin(-8.604868977581164,-17.3348862459467,-11.923191659094416),
|
||||
new Coin(24.81563047462934,-12.174170400556296,5.612049952487652),
|
||||
new Coin(-6.4854226987006305,0.34787283214634307,-17.2093293607182),
|
||||
new Coin(-14.50190371481413,20.88721463986533,7.923724946536855),
|
||||
new Coin(-13.980787439949077,-0.10719616576499978,22.24889144136683),
|
||||
new Coin(4.491305202472262,3.6813420775366277,10.03229664467681)
|
||||
];
|
||||
}
|
||||
|
||||
function createMountainCameras(width, height) {
|
||||
var cams = [];
|
||||
|
||||
var createCamera = function(position, target) {
|
||||
return new RecommendedCamera(
|
||||
50,
|
||||
width / height,
|
||||
1,
|
||||
100000,
|
||||
position,
|
||||
target
|
||||
);
|
||||
};
|
||||
|
||||
cams.push(
|
||||
createCamera(
|
||||
new THREE.Vector3(6.390950470631724,17.280677948120072,-10.027673035476619),
|
||||
new THREE.Vector3(3.407145269707846,3.751012364771242,27.496253407869986)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(1.8218030281265742,12.868464705566172,23.225042509186405),
|
||||
new THREE.Vector3(-35.819191507045865,-0.6612008777826581,22.903049332448994)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(-16.540494685269973,13.110251646113246,22.542769963619342),
|
||||
new THREE.Vector3(-27.881799604553773,-2.2838398465862237,-12.59121287126898)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(-22.09255502589394,7.505905597711714,-15.23412829383532),
|
||||
new THREE.Vector3(14.823279525934556,-4.1255169584417315,-5.138031589552474)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(-21.665778251110755,4.241815926756635,40.76683432842355),
|
||||
new THREE.Vector3(2.62922954212112,-7.389606629396811,11.19552043054259)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(14.384899444452842,4.759647095537105,30.122662109900055),
|
||||
new THREE.Vector3(25.246471433793317,-6.871775460616339,-6.575243324069596)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(20.6728438093429,-14.408979127185429,18.889993476410144),
|
||||
new THREE.Vector3(-13.929780518638935,-26.04040168333887,35.241397053374556)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(-26.825730322260814,-17.21406097233303,33.188195206615795),
|
||||
new THREE.Vector3(-12.326126408723896,-17.015972902810617,-4.090783420316271)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(-41.2311561559715,-11.714721125315961,2.070220579408691),
|
||||
new THREE.Vector3(-2.2066012462800373,-15.510910369724881,9.986852522420207)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(24.92926976320075,-11.374119469227288,-21.440813349326792),
|
||||
new THREE.Vector3(-7.328902834025087,-24.90378505257612,-2.040853300647978)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(-18.733128013636136,-12.129585933653297,-31.983290996466735),
|
||||
new THREE.Vector3(-1.6636179852017818,-25.659251517002126,1.566373332583197)
|
||||
),
|
||||
createCamera(
|
||||
new THREE.Vector3(-20.627345017019206,22.028686074349515,20.541790520954777),
|
||||
new THREE.Vector3(14.150384161446272,11.731784408247087,3.6751557271398525)
|
||||
)
|
||||
);
|
||||
|
||||
return cams;
|
||||
}
|
||||
|
||||
function resetMountainElements() {
|
||||
return {
|
||||
position : new THREE.Vector3(-20.558328115300082,23.601312087942762,-10.220633604814038),
|
||||
target : new THREE.Vector3(11.025356711105232,11.969889531789319,11.393733425161644)
|
||||
};
|
||||
}
|
||||
|
||||
function initMountain(camera, scene, coins) {
|
||||
addLight(scene);
|
||||
|
||||
var collidableObjects = [];
|
||||
initMountainScene(scene, collidableObjects, camera);
|
||||
|
||||
camera.resetElements = resetMountainElements();
|
||||
camera.collidableObjects = collidableObjects;
|
||||
|
||||
camera.speed = 0.005;
|
||||
camera.reset();
|
||||
camera.save();
|
||||
|
||||
scene.add(camera);
|
||||
|
||||
Coin.init();
|
||||
var tmp = createMountainCoins();
|
||||
|
||||
for (var i in tmp) {
|
||||
coins.push(tmp[i]);
|
||||
}
|
||||
|
||||
var otherCams = createMountainCameras(container_size.width(), container_size.height());
|
||||
var cameras = new CameraContainer(camera, otherCams);
|
||||
|
||||
otherCams.forEach(function(cam) {cam.addToScene(scene);});
|
||||
|
||||
setTimeout(function() { coins.forEach(function(coin) { coin.addToScene(scene); });}, 1000);
|
||||
return cameras;
|
||||
}
|
||||
|
||||
function initSponzaScene(scene, collidableObjects, camera) {
|
||||
|
||||
var loader = new ProgressiveLoaderGeometry('/static/data/sponza/sponza.obj', scene, camera, function(obj) {
|
||||
if (obj.material.name === 'chain' ||
|
||||
obj.material.name === 'leaf' ||
|
||||
obj.material.name === 'Material__57') {
|
||||
|
||||
THREEx.Transparency.push(obj);
|
||||
|
||||
}
|
||||
|
||||
obj.raycastable = true;
|
||||
|
||||
});
|
||||
|
||||
l = loader;
|
||||
loader.load();
|
||||
|
||||
|
||||
loader.getCamera = function() {
|
||||
var ret = loader.camera.toList();
|
||||
ret[0][0] *= 10;
|
||||
ret[0][1] *= 10;
|
||||
ret[0][2] *= 10;
|
||||
|
||||
ret[1][0] *= 10;
|
||||
ret[1][1] *= 10;
|
||||
ret[1][2] *= 10;
|
||||
|
||||
// Planes
|
||||
for (var i = 2; i < ret.length; i++) {
|
||||
|
||||
ret[i][3] *= 10;
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
loader.obj.scale.set(0.1,0.1,0.1);
|
||||
|
||||
collidableObjects.push(loader.obj);
|
||||
loader.obj.raycastable = true;
|
||||
|
||||
|
||||
|
||||
// ProgressiveLoader('/static/data/sponza/sponza.obj', scene,
|
||||
// function(obj) {
|
||||
// obj.scale.set(0.1,0.1,0.1);
|
||||
// collidableObjects.push(obj);
|
||||
// obj.raycastable = true;
|
||||
|
||||
// if (obj.material.name === 'chain' ||
|
||||
// obj.material.name === 'leaf' ||
|
||||
// obj.material.name === 'Material__57') {
|
||||
|
||||
// THREEx.Transparency.push(obj);
|
||||
// }
|
||||
|
||||
// }
|
||||
// );
|
||||
|
||||
}
|
||||
|
||||
function createSponzaCoins() {
|
||||
return [];
|
||||
}
|
||||
|
||||
function createSponzaCameras() {
|
||||
return [];
|
||||
}
|
||||
|
||||
function resetSponzaElements() {
|
||||
return {
|
||||
position: new THREE.Vector3(92.98373669520107,60.8877777990862,11.130138641670737),
|
||||
target: new THREE.Vector3(53.76696417668598,56.09739213575453,4.877382575136091)
|
||||
};
|
||||
}
|
||||
|
||||
function initSponza(camera, scene, coins) {
|
||||
|
||||
addLight(scene);
|
||||
|
||||
var collidableObjects = [];
|
||||
initSponzaScene(scene, collidableObjects, camera);
|
||||
|
||||
camera.resetElements = resetSponzaElements();
|
||||
camera.collidableObjects = collidableObjects;
|
||||
|
||||
camera.speed = 0.05;
|
||||
camera.reset();
|
||||
camera.save();
|
||||
|
||||
scene.add(camera);
|
||||
|
||||
Coin.init();
|
||||
var tmp = createSponzaCoins();
|
||||
|
||||
for (var i in tmp) {
|
||||
coins.push(tmp[i]);
|
||||
}
|
||||
|
||||
var otherCams = createSponzaCameras(container_size.width(), container_size.height());
|
||||
var cameras = new CameraContainer(camera, otherCams);
|
||||
|
||||
otherCams.forEach(function(cam) {cam.addToScene(scene);});
|
||||
|
||||
setTimeout(function() { coins.forEach(function(coin) { coin.addToScene(scene); });}, 1000);
|
||||
|
||||
|
||||
return cameras;
|
||||
|
||||
}
|
||||
169
js/l3d/src/utils/CameraSelecter.js
Normal file
169
js/l3d/src/utils/CameraSelecter.js
Normal file
@@ -0,0 +1,169 @@
|
||||
var CameraSelecter = function(renderer, scene, cameras, coins, buttonManager) {
|
||||
this.raycaster = new THREE.Raycaster();
|
||||
this.renderer = renderer;
|
||||
this.mouse = {};
|
||||
this.cameras = cameras;
|
||||
this.prev = {};
|
||||
this.buttonManager = buttonManager;
|
||||
this.scene = scene;
|
||||
this.coins = coins;
|
||||
};
|
||||
|
||||
CameraSelecter.prototype.pointedCamera = function() {
|
||||
var returnCamera;
|
||||
|
||||
var x = ( this.mouse.x / this.renderer.domElement.width ) * 2 - 1;
|
||||
var y = - (this.mouse.y / this.renderer.domElement.height) * 2 + 1;
|
||||
|
||||
var camera = this.cameras.mainCamera();
|
||||
|
||||
if (camera.pointerLocked) {
|
||||
|
||||
this.mouse.x = this.renderer.domElement.width/2 ;
|
||||
this.mouse.y = this.renderer.domElement.height/2 ;
|
||||
x = 0;
|
||||
y = 0;
|
||||
|
||||
}
|
||||
|
||||
var vector = new THREE.Vector3(x, y, 0.5);
|
||||
vector.unproject(camera);
|
||||
|
||||
this.raycaster.set(camera.position, vector.sub(camera.position).normalize());
|
||||
|
||||
var intersects = this.raycaster.intersectObjects(this.scene.children, true);
|
||||
|
||||
if ( intersects.length > 0 ) {
|
||||
var minDistance;
|
||||
var bestIndex;
|
||||
|
||||
// Looking for cameras
|
||||
for (var i in intersects) {
|
||||
if (intersects[i].object.raycastable && !(intersects[i].object instanceof THREE.Line)) {
|
||||
if ((intersects[i].distance > 0.5 && minDistance === undefined) || (intersects[i].distance < minDistance )) {
|
||||
if (!(intersects[i].object instanceof THREE.Mesh && intersects[i].object.material.opacity < 0.1)) {
|
||||
minDistance = intersects[i].distance;
|
||||
bestIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bestIndex !== undefined) {
|
||||
// if (this.cameras.getById(intersects[bestIndex].object.parent.id) !== undefined) {
|
||||
var obj = intersects[bestIndex].object;
|
||||
|
||||
for (var coin in this.coins) {
|
||||
if (obj === this.coins[coin].mesh) {
|
||||
return this.coins[coin];
|
||||
}
|
||||
}
|
||||
this.currentPointedCamera = this.cameras.getByObject(intersects[bestIndex].object);
|
||||
return this.currentPointedCamera;
|
||||
// }
|
||||
}
|
||||
}
|
||||
this.currentPointedCamera = null;
|
||||
};
|
||||
|
||||
CameraSelecter.prototype.update = function(event, y) {
|
||||
var e;
|
||||
|
||||
if (event !== undefined) {
|
||||
this.mouse.x = event.offsetX === undefined ? event.layerX : event.offsetX;
|
||||
this.mouse.y = event.offsetY === undefined ? event.layerY : event.offsetY;
|
||||
}
|
||||
|
||||
if (y !== undefined) {
|
||||
this.mouse.x = this.renderer.domElement.width/2;
|
||||
this.mouse.y = this.renderer.domElement.height/2;
|
||||
}
|
||||
|
||||
var previousCamera = this.currentPointedCamera;
|
||||
var hovered = this.pointedCamera();
|
||||
|
||||
if (hovered !== undefined && !(hovered instanceof Coin)) {
|
||||
if (hovered !== previousCamera) {
|
||||
// log it
|
||||
e = new BD.Event.Hovered();
|
||||
e.start = true;
|
||||
e.arrow_id = this.cameras.cameras.indexOf(this.currentPointedCamera);
|
||||
e.send();
|
||||
|
||||
this.prev.x = this.mouse.x;
|
||||
this.prev.y = this.mouse.y;
|
||||
}
|
||||
this.prev.camera = hovered;
|
||||
this.prev.go = true;
|
||||
} else {
|
||||
if (this.prev.go) {
|
||||
// Log if previous was not null
|
||||
e = new BD.Event.Hovered();
|
||||
e.start = false;
|
||||
e.arrow_id = null;
|
||||
e.send();
|
||||
}
|
||||
this.prev.go = false;
|
||||
}
|
||||
|
||||
document.getElementById('container').style.cursor = hovered ? "pointer" : "auto";
|
||||
|
||||
if (this.cameras.mainCamera().pointerLocked)
|
||||
this.cameras.mainCamera().mousePointer.render(hovered ? MousePointer.RED : MousePointer.BLACK);
|
||||
|
||||
};
|
||||
|
||||
CameraSelecter.prototype.click = function(event) {
|
||||
var e;
|
||||
var newCamera = this.pointedCamera();
|
||||
|
||||
if (newCamera !== undefined && !(newCamera instanceof Coin)) {
|
||||
|
||||
e = new BD.Event.ArrowClicked();
|
||||
e.arrow_id = this.cameras.cameras.indexOf(newCamera);
|
||||
e.send();
|
||||
|
||||
newCamera.check();
|
||||
this.cameras.mainCamera().moveHermite(newCamera);
|
||||
buttonManager.updateElements();
|
||||
|
||||
} else if (newCamera instanceof Coin) {
|
||||
|
||||
// Coin found, notify server
|
||||
e = new BD.Event.CoinClicked();
|
||||
e.coin_id = this.coins.indexOf(newCamera);
|
||||
e.send();
|
||||
newCamera.get();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
CameraSelecter.prototype.clickPointer = function(event) {
|
||||
var e;
|
||||
|
||||
if (this.cameras.mainCamera().pointerLocked) {
|
||||
|
||||
var newCamera = this.pointedCamera();
|
||||
|
||||
if (newCamera !== undefined && !(newCamera instanceof Coin)) {
|
||||
|
||||
e = new BD.Event.ArrowClicked();
|
||||
e.arrow_id = this.cameras.cameras.indexOf(newCamera);
|
||||
e.send();
|
||||
|
||||
newCamera.check();
|
||||
this.cameras.mainCamera().moveHermite(newCamera);
|
||||
buttonManager.updateElements();
|
||||
|
||||
} else if (newCamera instanceof Coin) {
|
||||
|
||||
// Coin found, notify server
|
||||
e = new BD.Event.CoinClicked();
|
||||
e.coin_id = this.coins.indexOf(newCamera);
|
||||
e.send();
|
||||
newCamera.get();
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
77
js/l3d/src/utils/History.js
Normal file
77
js/l3d/src/utils/History.js
Normal file
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Represents the history of an object
|
||||
* @constructor
|
||||
*/
|
||||
var History = function() {
|
||||
/**
|
||||
* Stores the different states of the object
|
||||
* @type {Object[]}
|
||||
*/
|
||||
this.states = [];
|
||||
|
||||
/**
|
||||
* Represents the position in the history we're at
|
||||
* @type {Number}
|
||||
*/
|
||||
this.index = -1;
|
||||
|
||||
/**
|
||||
* Represents the number of elements in the history
|
||||
* @type {Number}
|
||||
*/
|
||||
this.size = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Appends a new state at the end of the history
|
||||
* @param {Object} state the state to append
|
||||
*/
|
||||
History.prototype.addState = function(state) {
|
||||
++this.index;
|
||||
this.size = this.index + 1;
|
||||
this.states[this.size-1] = state;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the previous state and change the index to the previous state (so you can redo)
|
||||
*/
|
||||
History.prototype.undo = function() {
|
||||
if (this.undoable()) {
|
||||
this.index--;
|
||||
return this.currentState();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the next state and change the index to the next state (so you can re-undo)
|
||||
*/
|
||||
History.prototype.redo = function() {
|
||||
if (this.redoable()) {
|
||||
this.index++;
|
||||
return this.currentState();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if there is a undo possibility
|
||||
* @returns {Boolean} true if undo is possible, false otherwise
|
||||
*/
|
||||
History.prototype.undoable = function() {
|
||||
return this.index > 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if there is a redo possibility
|
||||
* @returns {Boolean} true if redo is possible, false otherwise
|
||||
*/
|
||||
History.prototype.redoable = function() {
|
||||
return this.index < this.size - 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the current state in the history
|
||||
* @returns {Object} the current state in the history
|
||||
*/
|
||||
History.prototype.currentState = function() {
|
||||
return this.states[this.index];
|
||||
};
|
||||
242
js/l3d/src/utils/List.js
Normal file
242
js/l3d/src/utils/List.js
Normal file
@@ -0,0 +1,242 @@
|
||||
var utils = (function() {
|
||||
|
||||
var utils = {};
|
||||
|
||||
// Defines a double linked-list class
|
||||
utils.List = function() {
|
||||
this._size = 0;
|
||||
this._begin = null;
|
||||
this._end = null;
|
||||
};
|
||||
|
||||
// Returns the number of element of a list
|
||||
utils.List.prototype.size = function() {
|
||||
return this._size;
|
||||
};
|
||||
|
||||
// Pushes an element to the end of a class
|
||||
utils.List.prototype.push = function(element) {
|
||||
if (this._size === 0) {
|
||||
this._begin = { data : element, next: null, prev: null };
|
||||
this._end = this._begin;
|
||||
this._size = 1;
|
||||
} else {
|
||||
var newObject = { data: element, next: null, prev: this._end };
|
||||
this._end.next = newObject;
|
||||
this._end = newObject;
|
||||
this._size++;
|
||||
}
|
||||
};
|
||||
|
||||
// Sort the list
|
||||
utils.List.prototype.sort = function(comparator) {
|
||||
|
||||
if (comparator === undefined) {
|
||||
comparator = priv.defaultComparator;
|
||||
}
|
||||
|
||||
var array = [];
|
||||
this.forEach(function(elt) {
|
||||
array.push(elt);
|
||||
});
|
||||
|
||||
array.sort(function(a, b) {
|
||||
return comparator(a, b);
|
||||
});
|
||||
|
||||
var size = this.size();
|
||||
this.clear();
|
||||
|
||||
for (var i = 0; i < size; i++) {
|
||||
this.push(array[i]);
|
||||
}
|
||||
};
|
||||
|
||||
// Remove last element and returns it
|
||||
utils.List.prototype.pop = function() {
|
||||
var tmp = this._end;
|
||||
this._end = null;
|
||||
return tmp.data;
|
||||
};
|
||||
|
||||
// Apply a function to each element of the list
|
||||
utils.List.prototype.forEach = function(callback) {
|
||||
var chain = this._begin;
|
||||
|
||||
while (chain !== null) {
|
||||
callback(chain.data);
|
||||
chain = chain.next;
|
||||
}
|
||||
};
|
||||
|
||||
// Apply a function to each element of the list (starting from the end)
|
||||
utils.List.prototype.forEachInverse = function(callback) {
|
||||
var chain = this._end;
|
||||
|
||||
while (chain !== null) {
|
||||
callback(chain.data);
|
||||
chain = chain.prev;
|
||||
}
|
||||
};
|
||||
|
||||
// Get ith element of the list
|
||||
utils.List.prototype.at = function(ith) {
|
||||
if (ith < 0 || ith >= this.size()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var chain = this._begin;
|
||||
for (var i = 0; i < ith; i++) {
|
||||
chain = chain.next;
|
||||
}
|
||||
|
||||
return chain.data;
|
||||
};
|
||||
|
||||
// Clear the list
|
||||
utils.List.prototype.clear = function() {
|
||||
this._begin = null;
|
||||
this._end = null;
|
||||
this._size = 0;
|
||||
};
|
||||
|
||||
// Insert an element at the right place in the list
|
||||
// Precondition : list must be sorted
|
||||
utils.List.prototype.insertSorted = function(elt, comparator) {
|
||||
var newElement;
|
||||
|
||||
if (comparator === undefined) {
|
||||
comparator = priv.defaultComparator;
|
||||
}
|
||||
|
||||
if (this._begin === null) {
|
||||
// Inserted in front (empty list)
|
||||
this.push(elt);
|
||||
} else if (comparator(this._begin.data, elt) > 0) {
|
||||
// Inserted in front (smallest element)
|
||||
newElement = {prev: null, next: this._begin, data: elt};
|
||||
|
||||
this._begin.prev = newElement;
|
||||
|
||||
this._begin = newElement;
|
||||
this._size ++;
|
||||
|
||||
} else if (comparator(this._end.data, elt) < 0) {
|
||||
// Inserted in end
|
||||
this.push(elt);
|
||||
} else {
|
||||
// Inserted in the middle
|
||||
var chain = this._begin;
|
||||
|
||||
while (chain.next !== null) {
|
||||
// If chain < elt < chain.next
|
||||
if (comparator(chain.next.data, elt) > 0) {
|
||||
newElement = {data: elt, next: chain.next, prev: chain};
|
||||
if (chain.next) {
|
||||
chain.next.prev = newElement;
|
||||
}
|
||||
chain.next = newElement;
|
||||
this._size ++;
|
||||
return;
|
||||
}
|
||||
|
||||
// Next step
|
||||
chain = chain.next;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Check if a list is sorted of not
|
||||
utils.List.prototype.isSorted = function(comparator) {
|
||||
var chain = this._begin;
|
||||
|
||||
if (comparator === undefined) {
|
||||
comparator = priv.defaultComparator;
|
||||
}
|
||||
|
||||
while (chain.next !== null) {
|
||||
if (comparator(chain.data, chain.next.data) > 0) {
|
||||
return false;
|
||||
}
|
||||
chain = chain.next;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
// Gives an iterator to the begin of the list
|
||||
utils.List.prototype.begin = function() {
|
||||
return new utils.List.Iterator(this._begin, 0);
|
||||
};
|
||||
|
||||
// Gives an iterator to the end of the list
|
||||
utils.List.prototype.end = function() {
|
||||
return new utils.List.Iterator(this._end, this.size() - 1);
|
||||
};
|
||||
|
||||
// Class iterator
|
||||
utils.List.Iterator = function(chain, counter) {
|
||||
this._chain = chain;
|
||||
this._counter = counter;
|
||||
};
|
||||
|
||||
// Go to the next element
|
||||
utils.List.Iterator.prototype.next = function() {
|
||||
this._chain = this._chain.next;
|
||||
this._counter ++;
|
||||
};
|
||||
|
||||
// Go to the previous element
|
||||
utils.List.Iterator.prototype.prev = function() {
|
||||
this._chain = this._chain.prev;
|
||||
this._counter --;
|
||||
};
|
||||
|
||||
// Return the current element
|
||||
utils.List.Iterator.prototype.get = function() {
|
||||
return this._chain.data;
|
||||
};
|
||||
|
||||
// Check if there is another element next
|
||||
utils.List.Iterator.prototype.hasNext = function() {
|
||||
return this._chain.next !== null;
|
||||
};
|
||||
|
||||
// Check if there is another element before
|
||||
utils.List.Iterator.prototype.hasPrev = function() {
|
||||
return this._chain.prev !== null;
|
||||
};
|
||||
|
||||
// Compares to another iterator of the same list
|
||||
utils.List.Iterator.prototype.lowerThan = function(it2) {
|
||||
return utils.distance(this, it2) > 0;
|
||||
};
|
||||
|
||||
// Compares to another iterator of the same list
|
||||
utils.List.Iterator.prototype.greaterThan = function(it2) {
|
||||
return utils.distance(this, it2) < 0;
|
||||
};
|
||||
|
||||
// Returns the distance between two iterators of the same list
|
||||
utils.distance = function(it1, it2) {
|
||||
return it2._counter - it1._counter;
|
||||
};
|
||||
|
||||
priv = {};
|
||||
|
||||
priv.defaultComparator = function(a,b) {
|
||||
if (a < b)
|
||||
return -1;
|
||||
if (a > b)
|
||||
return 1;
|
||||
return 0;
|
||||
};
|
||||
|
||||
// Support for NodeJs
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = utils;
|
||||
} else {
|
||||
return utils;
|
||||
}
|
||||
|
||||
})();
|
||||
17
js/l3d/src/utils/ListTest.js
Normal file
17
js/l3d/src/utils/ListTest.js
Normal file
@@ -0,0 +1,17 @@
|
||||
var list = new utils.List();
|
||||
var size = 100;
|
||||
|
||||
for (var i = 0; i < size; i++) {
|
||||
list.push(Math.random());
|
||||
}
|
||||
|
||||
// For with C++-style iterator
|
||||
// for (var it = list.begin(); it.lowerThan(list.end()); it.next()) {
|
||||
// console.log(it.get());
|
||||
// }
|
||||
|
||||
console.log(false === list.isSorted());
|
||||
list.sort();
|
||||
console.log(list.isSorted());
|
||||
|
||||
console.log(size === list.size());
|
||||
116
js/l3d/src/utils/Logger.js
Normal file
116
js/l3d/src/utils/Logger.js
Normal file
@@ -0,0 +1,116 @@
|
||||
var BD = {};
|
||||
|
||||
BD.Private = {};
|
||||
|
||||
BD.Private.sendData = function(url, data) {
|
||||
if (BD.Private.enabled) {
|
||||
// Append time to data
|
||||
data.time = Date.now() / 1000;
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", url, true);
|
||||
xhr.setRequestHeader("Content-type", "application/json;charset=UTF-8");
|
||||
|
||||
// xhr.onreadystatechange = function() {
|
||||
// if(xhr.readyState == 4 && xhr.status == 200) {
|
||||
// console.log("Done : " + xhr.responseText);
|
||||
// }
|
||||
// }
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
};
|
||||
|
||||
BD.Private.enabled = true;
|
||||
|
||||
BD.enable = function() {
|
||||
BD.Private.enabled = true;
|
||||
};
|
||||
|
||||
BD.disable = function() {
|
||||
BD.Private.enabled = false;
|
||||
};
|
||||
|
||||
BD.Private.compactCamera = function(camera) {
|
||||
return {
|
||||
position: {
|
||||
x: camera.position.x,
|
||||
y: camera.position.y,
|
||||
z: camera.position.z
|
||||
},
|
||||
target: {
|
||||
x: camera.target.x,
|
||||
y: camera.target.y,
|
||||
z: camera.target.z
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
BD.Event = {};
|
||||
|
||||
BD.Event.ArrowClicked = function() {};
|
||||
BD.Event.ArrowClicked.prototype.send = function() {
|
||||
var url = "/arrow-clicked";
|
||||
var data = {arrow_id: this.arrow_id};
|
||||
BD.Private.sendData(url, data);
|
||||
};
|
||||
|
||||
BD.Event.CoinClicked = function() {};
|
||||
BD.Event.CoinClicked.prototype.send = function() {
|
||||
var url = "/coin-clicked";
|
||||
var data = {coin_id: this.coin_id};
|
||||
BD.Private.sendData(url, data);
|
||||
};
|
||||
|
||||
BD.Event.KeyboardEvent = function() {};
|
||||
BD.Event.KeyboardEvent.prototype.send = function() {
|
||||
var url = "/keyboard-event";
|
||||
|
||||
var data = {
|
||||
camera: BD.Private.compactCamera(this.camera)
|
||||
};
|
||||
|
||||
BD.Private.sendData(url, data);
|
||||
};
|
||||
|
||||
BD.Event.ResetClicked = function() {};
|
||||
BD.Event.ResetClicked.prototype.send = function() {
|
||||
var url = "/reset-clicked";
|
||||
var data = {};
|
||||
BD.Private.sendData(url, data);
|
||||
};
|
||||
|
||||
BD.Event.PreviousNextClicked = function() {};
|
||||
BD.Event.PreviousNextClicked.prototype.send = function() {
|
||||
var url = "/previous-next-clicked";
|
||||
var data = {
|
||||
// casts previous to boolean
|
||||
previous: this.previous,
|
||||
camera: BD.Private.compactCamera(this.camera)
|
||||
};
|
||||
|
||||
BD.Private.sendData(url, data);
|
||||
};
|
||||
|
||||
BD.Event.Hovered = function() {};
|
||||
BD.Event.Hovered.prototype.send = function() {
|
||||
var url = "/hovered";
|
||||
var data = {
|
||||
start: this.start,
|
||||
arrow_id: this.arrow_id
|
||||
};
|
||||
|
||||
BD.Private.sendData(url, data);
|
||||
};
|
||||
|
||||
BD.Event.Fps = function() {};
|
||||
BD.Event.Fps.prototype.send = function() {
|
||||
|
||||
var url = "/fps";
|
||||
var data = {
|
||||
fps: this.fps
|
||||
};
|
||||
|
||||
BD.Private.sendData(url, data);
|
||||
|
||||
};
|
||||
49
js/l3d/src/utils/Objects.js
Normal file
49
js/l3d/src/utils/Objects.js
Normal file
@@ -0,0 +1,49 @@
|
||||
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.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);
|
||||
};
|
||||
Reference in New Issue
Block a user