Changed stuff and added doc

This commit is contained in:
Thomas FORGIONE 2015-06-23 15:31:23 +02:00
parent 6242e6f122
commit 5e445a8c28
8 changed files with 475 additions and 35200 deletions

View File

@ -5,13 +5,12 @@ models written with Node.js.
It is hosted by [OpenShift](https://www.openshift.com/) at It is hosted by [OpenShift](https://www.openshift.com/) at
[3dinterface.no-ip.org](http://3dinterface.no-ip.org). [3dinterface.no-ip.org](http://3dinterface.no-ip.org).
## To run a local server ## Database setup
### Database setup
First you need to configure the database. You can create a postgres database First you need to configure the database. You can create a postgres database
where you want, and you can initialize it by running the script where you want, and you can initialize it by running the script
`sql/backup.pgsql`. `sql/backup.pgsql`.
### Nodejs configuration ## Nodejs configuration
Then, you have to set up nodejs to access to your database. Basically, you have Then, you have to set up nodejs to access to your database. Basically, you have
to create a file `private.js` at the root of the repository looking like this : to create a file `private.js` at the root of the repository looking like this :
@ -20,21 +19,21 @@ module.exports.url = ... // the url to connect to your database
module.exports.secret = ... // A secret string used to hash stuff module.exports.secret = ... // A secret string used to hash stuff
``` ```
### Compiling the static js files ## Compiling the static js files
There are two ways to compile the static js files : There are two ways to compile the static js files :
- either you don't mind not minifying the code, and you can use `compiler.sh` to compile - either you don't mind not minifying the code, and you can use `compiler.sh` to compile
- or you absolutely want to minify the code, and you'll need - or you absolutely want to minify the code, and you'll need
[closure-compiler](https://github.com/google/closure-compiler) [closure-compiler](https://github.com/google/closure-compiler)
#### Compiling without minifying ### Compiling without minifying
To compile without minifying, simply run To compile without minifying, simply run
``` ```
make make
``` ```
in `static/js`. in `static/js`.
#### Compiling and minifying ### Compiling and minifying
To compile and minify the js files, you have to run To compile and minify the js files, you have to run
``` ```
make TYPE=RELEASE make TYPE=RELEASE
@ -43,10 +42,10 @@ make TYPE=RELEASE
If it doesn't work, check in the `Makefile` that the path to `closure-compiler.jar` If it doesn't work, check in the `Makefile` that the path to `closure-compiler.jar`
is correct. is correct.
#### Check if it worked ### Check if it worked
If it worked, you should see lots of files in `*.min.js` in your `static/js` directory. If it worked, you should see lots of files in `*.min.js` in your `static/js` directory.
### Running the server ## Running the server
As usual with NodeJS, it's quite easy to test. Just ensure you have `node` As usual with NodeJS, it's quite easy to test. Just ensure you have `node`
installed on your machine, clone this repo somewhere, and then, in the repo do installed on your machine, clone this repo somewhere, and then, in the repo do

View File

@ -1,8 +1,14 @@
var fs = require('fs'); var fs = require('fs');
var mesh = require('./Mesh.js'); var mesh = require('./Mesh.js');
/**
* @namespace
*/
var geo = {}; var geo = {};
/**
* @private
*/
function bisect(items, x, lo, hi) { function bisect(items, x, lo, hi) {
var mid; var mid;
if (typeof(lo) == 'undefined') lo = 0; if (typeof(lo) == 'undefined') lo = 0;
@ -15,10 +21,16 @@ function bisect(items, x, lo, hi) {
return lo; return lo;
} }
/**
* @private
*/
function insort(items, x) { function insort(items, x) {
items.splice(bisect(items, x), 0, x); items.splice(bisect(items, x), 0, x);
} }
/**
* @private
*/
function partialSort(items, k, comparator) { function partialSort(items, k, comparator) {
var smallest = items.slice(0, k).sort(), var smallest = items.slice(0, k).sort(),
max = smallest[k-1]; max = smallest[k-1];
@ -35,18 +47,54 @@ function partialSort(items, k, comparator) {
return smallest; return smallest;
} }
/**
* A class that streams easily a mesh via socket.io
* @memberOf geo
* @constructor
* @param {string} path to the mesh
* @param {function} callback to execute when the mesh streamer is loaded
*/
geo.MeshStreamer = function(path, callback) { geo.MeshStreamer = function(path, callback) {
// Different parts of a obj (a mesh per material) /**
* array of each part of the mesh
* @type {mesh.Mesh[]}
*/
this.meshes = []; this.meshes = [];
// In meshes, vertices and texture coords are shared /**
* array of the vertices of the meshes (all merged)
* @type {mesh.Vertex[]}
*/
this.vertices = []; this.vertices = [];
/**
* array of the faces of the meshes (all merged)
* @type {mesh.Face[]}
*/
this.faces = []; this.faces = [];
/**
* array of the normals of the meshes (all merged)
* @type {mesh.Normal[]}
*/
this.normals = []; this.normals = [];
/**
* array of the texture coordinates (all merged)
* @type {mesh.TexCoord[]}
*/
this.texCoords = []; this.texCoords = [];
/**
* array of the faces in a nice order for sending
* @type {mesh.Face[]}
*/
this.orderedFaces = []; this.orderedFaces = [];
// Chunk size /**
* Number of element to send by packet
* @type {Number}
*/
this.chunk = 1000; this.chunk = 1000;
if (path !== undefined) { if (path !== undefined) {
@ -59,7 +107,11 @@ geo.MeshStreamer = function(path, callback) {
} }
} }
// Returns the function that compares two faces /**
* Compute a function that can compare two faces
* @param {Camera} camera a camera seeing or not face
* @returns the function that compares two faces : the higher face is the most interesting for the camera
*/
geo.MeshStreamer.prototype.faceComparator = function(camera) { geo.MeshStreamer.prototype.faceComparator = function(camera) {
var self = this; var self = this;
@ -131,6 +183,11 @@ geo.MeshStreamer.prototype.faceComparator = function(camera) {
} }
} }
/**
* Loads a obj file
* @param {string} path the path to the file
* @param {function} callback the callback to call when the mesh is loaded
*/
geo.MeshStreamer.prototype.loadFromFile = function(path, callback) { geo.MeshStreamer.prototype.loadFromFile = function(path, callback) {
var self = this; var self = this;
fs.readFile(path, function(err, data) { fs.readFile(path, function(err, data) {
@ -228,6 +285,10 @@ geo.MeshStreamer.prototype.loadFromFile = function(path, callback) {
}); });
} }
/**
* Initialize the socket.io callback
* @param {socket} socket the socket to initialize
*/
geo.MeshStreamer.prototype.start = function(socket) { geo.MeshStreamer.prototype.start = function(socket) {
this.meshIndex = 0; this.meshIndex = 0;
@ -278,6 +339,10 @@ geo.MeshStreamer.prototype.start = function(socket) {
}); });
} }
/**
* Prepare the array of materials
* @return array the array to send with all materials of the current mesh
*/
geo.MeshStreamer.prototype.nextMaterials = function() { geo.MeshStreamer.prototype.nextMaterials = function() {
var data = []; var data = [];
@ -302,6 +367,12 @@ geo.MeshStreamer.prototype.nextMaterials = function() {
} }
/**
* Prepare the next elements
* @param {camera} _camera a camera that can be usefull to do smart streaming (stream
* only interesting parts according to the camera
* @returns {array} an array of elements ready to send
*/
geo.MeshStreamer.prototype.nextElements = function(_camera) { geo.MeshStreamer.prototype.nextElements = function(_camera) {
// Prepare camera (and scale to model) // Prepare camera (and scale to model)
@ -388,7 +459,7 @@ geo.MeshStreamer.prototype.nextElements = function(_camera) {
if ( if (
direction.x * v1.x + direction.y * v1.y + direction.z * v1.z < 0 && direction.x * v1.x + direction.y * v1.y + direction.z * v1.z < 0 &&
direction.x * v2.x + direction.y * v2.y + direction.z * v2.z < 0 && direction.x * v2.x + direction.y * v2.y + direction.z * v2.z < 0 &&
direction.x * v3.x + direction.y * v3.y + direction.z * v3.z < 0 direction.x * v3.x + direction.y * v3.y + direction.z * v3.z < 0
) { ) {
continue; continue;

77
js/History.js Normal file
View 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];
}

View File

@ -70,6 +70,7 @@ StreamingSimulator:
PrototypeTools: PrototypeTools:
$(CLOSURE) $(OPT) \ $(CLOSURE) $(OPT) \
--js History.js \
--js StaticPath.js \ --js StaticPath.js \
--js Hermite.js \ --js Hermite.js \
--js Camera.js \ --js Camera.js \

View File

@ -1,7 +1,15 @@
// class camera extends THREE.PerspectiveCamera /**
* Represents a camera that can be used easily
* @constructor
* @augments THREE.PerspectiveCamera
*/
var PointerCamera = function() { var PointerCamera = function() {
THREE.PerspectiveCamera.apply(this, arguments); THREE.PerspectiveCamera.apply(this, arguments);
/**
* A reference to the renderer
* @type {THREE.Renderer}
*/
this.renderer = arguments[4]; this.renderer = arguments[4];
if (arguments[5] === undefined) if (arguments[5] === undefined)
@ -9,38 +17,118 @@ var PointerCamera = function() {
else else
listenerTarget = arguments[5]; listenerTarget = arguments[5];
// Set Position /**
* Theta angle of the camera
* @type {Number}
*/
this.theta = Math.PI; this.theta = Math.PI;
/**
* Phi angle of the camera
* @type {Number}
*/
this.phi = Math.PI; this.phi = Math.PI;
// this.keyboard = undefined; /**
* Indicates if the camera is following a linear motion
* @type {Boolean}
*/
this.moving = false; this.moving = false;
/**
* Indicates if the user is dragging the camera
* @type {Boolean}
*/
this.dragging = false; this.dragging = false;
/**
* Current position of the cursor
* @type {Object}
*/
this.mouse = {x: 0, y: 0}; this.mouse = {x: 0, y: 0};
/**
* Current movement of the cursor
* @type {Object}
*/
this.mouseMove = {x: 0, y: 0}; this.mouseMove = {x: 0, y: 0};
/**
// Stuff for rendering * Current position of the camera (optical center)
* @type {THREE.Vector}
*/
this.position = new THREE.Vector3(); this.position = new THREE.Vector3();
/**
* Current direction of the camera
* @type {THREE.Vector}
*/
this.forward = new THREE.Vector3(); this.forward = new THREE.Vector3();
/**
* Vector pointing to the left of the camera
* @type {THREE.Vector}
*/
this.left = new THREE.Vector3(); this.left = new THREE.Vector3();
/**
* Point that the camera is targeting
* @type {THREE.Vector}
*/
this.target = new THREE.Vector3(0,1,0); this.target = new THREE.Vector3(0,1,0);
// Stuff for events /**
* 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 = {}; this.motion = {};
/**
* Sentitivity of the mouse
* @type {Number}
*/
this.sensitivity = 0.05; this.sensitivity = 0.05;
/**
* Speed of the camera
* @type {Number}
*/
this.speed = 1; this.speed = 1;
// Raycaster for collisions /**
* Raycaster used to compute collisions
* @type {THREE.Raycaster}
*/
this.raycaster = new THREE.Raycaster(); this.raycaster = new THREE.Raycaster();
// Create history object /**
* History of the moves of the camera
* @type {History}
*/
this.history = new History(); this.history = new History();
// Variable for lock pointer /**
* Option to enable or disable the pointer lock
* @type {Boolean}
*/
this.shouldLock = true; this.shouldLock = true;
/**
* Current state of the pointer (locked or not)
* @type {Boolean}
*/
this.pointerLocked = false; this.pointerLocked = false;
// Set events from the document // Set events from the document
@ -66,15 +154,32 @@ var PointerCamera = function() {
// listenerTarget.addEventListener('mouseup', function() { console.log("mouseup");}, false); // listenerTarget.addEventListener('mouseup', function() { console.log("mouseup");}, false);
listenerTarget.addEventListener('mouseout', onMouseUp, false); listenerTarget.addEventListener('mouseout', onMouseUp, false);
/**
* Option to enable or disable the collisions
* @type {Boolean}
*/
this.collisions = true; 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; this.shouldLogCameraAngles = true;
/**
* The camera we will move to when we'll reset the camera
* @param {Object}
*/
this.resetElements = resetBobombElements(); this.resetElements = resetBobombElements();
} }
PointerCamera.prototype = Object.create(THREE.PerspectiveCamera.prototype); PointerCamera.prototype = Object.create(THREE.PerspectiveCamera.prototype);
PointerCamera.prototype.constructor = PointerCamera; 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() { PointerCamera.prototype.lockPointer = function() {
if (this.shouldLock) { if (this.shouldLock) {
@ -97,6 +202,9 @@ PointerCamera.prototype.lockPointer = function() {
} }
/**
* Update the camera when the pointer lock changes state
*/
PointerCamera.prototype.onPointerLockChange = function() { PointerCamera.prototype.onPointerLockChange = function() {
document.pointerLockElement = document.pointerLockElement =
@ -117,7 +225,10 @@ PointerCamera.prototype.onPointerLockChange = function() {
} }
// Update function /**
* Update the position of the camera
* @param {Number} time number of milliseconds between the previous and the next frame
*/
PointerCamera.prototype.update = function(time) { PointerCamera.prototype.update = function(time) {
if (this.moving) { if (this.moving) {
this.linearMotion(time); this.linearMotion(time);
@ -128,6 +239,10 @@ PointerCamera.prototype.update = function(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) { PointerCamera.prototype.linearMotion = function(time) {
var position_direction = Tools.diff(this.new_position, this.position); var position_direction = Tools.diff(this.new_position, this.position);
var target_direction = Tools.diff(this.new_target, this.target); var target_direction = Tools.diff(this.new_target, this.target);
@ -142,6 +257,10 @@ PointerCamera.prototype.linearMotion = function(time) {
} }
} }
/**
* 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) { PointerCamera.prototype.hermiteMotion = function(time) {
var eval = this.hermitePosition.eval(this.t); var eval = this.hermitePosition.eval(this.t);
this.position.x = eval.x; this.position.x = eval.x;
@ -158,6 +277,10 @@ PointerCamera.prototype.hermiteMotion = function(time) {
} }
} }
/**
* 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) { PointerCamera.prototype.normalMotion = function(time) {
// Update angles // Update angles
if (this.motion.increasePhi) {this.phi += this.sensitivity * time / 20; this.changed = true; } if (this.motion.increasePhi) {this.phi += this.sensitivity * time / 20; this.changed = true; }
@ -224,6 +347,9 @@ PointerCamera.prototype.normalMotion = function(time) {
this.target.add(forward); this.target.add(forward);
} }
/**
* Reset the camera to its resetElements, and finishes any motion
*/
PointerCamera.prototype.reset = function() { PointerCamera.prototype.reset = function() {
this.resetPosition(); this.resetPosition();
this.moving = false; this.moving = false;
@ -231,12 +357,18 @@ PointerCamera.prototype.reset = function() {
(new BD.Event.ResetClicked()).send(); (new BD.Event.ResetClicked()).send();
} }
/**
* Reset the position of th camera
*/
PointerCamera.prototype.resetPosition = function() { PointerCamera.prototype.resetPosition = function() {
this.position.copy(this.resetElements.position); this.position.copy(this.resetElements.position);
this.target.copy(this.resetElements.target); this.target.copy(this.resetElements.target);
this.anglesFromVectors(); this.anglesFromVectors();
} }
/**
* Computes the vectors (forward, left, ...) according to theta and phi
*/
PointerCamera.prototype.vectorsFromAngles = function() { PointerCamera.prototype.vectorsFromAngles = function() {
// Update direction // Update direction
this.forward.y = Math.sin(this.phi); this.forward.y = Math.sin(this.phi);
@ -248,6 +380,9 @@ PointerCamera.prototype.vectorsFromAngles = function() {
} }
/**
* Computes theta and phi according to the vectors (forward, left, ...)
*/
PointerCamera.prototype.anglesFromVectors = function() { PointerCamera.prototype.anglesFromVectors = function() {
var forward = Tools.diff(this.target, this.position); var forward = Tools.diff(this.target, this.position);
forward.normalize(); forward.normalize();
@ -259,6 +394,11 @@ PointerCamera.prototype.anglesFromVectors = function() {
this.theta = Math.atan2(forward.x, forward.z); 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) { PointerCamera.prototype.move = function(otherCamera, toSave) {
if (toSave === undefined) if (toSave === undefined)
toSave = true; toSave = true;
@ -281,6 +421,11 @@ PointerCamera.prototype.move = function(otherCamera, toSave) {
} }
} }
/**
* 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) { PointerCamera.prototype.moveHermite = function(otherCamera, toSave) {
if (toSave === undefined) if (toSave === undefined)
toSave = true; toSave = true;
@ -309,6 +454,11 @@ PointerCamera.prototype.moveHermite = function(otherCamera, toSave) {
} }
} }
/**
* 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) { PointerCamera.prototype.isColliding = function(direction) {
this.raycaster.set(this.position, direction.clone().normalize()); this.raycaster.set(this.position, direction.clone().normalize());
var intersects = this.raycaster.intersectObjects(this.collidableObjects, true); var intersects = this.raycaster.intersectObjects(this.collidableObjects, true);
@ -323,15 +473,25 @@ PointerCamera.prototype.isColliding = function(direction) {
return false; return false;
} }
// Look function /**
* Look method. Equivalent to gluLookAt for the current camera
*/
PointerCamera.prototype.look = function() { PointerCamera.prototype.look = function() {
this.lookAt(this.target); this.lookAt(this.target);
} }
/**
* Adds the camera to the scene
*/
PointerCamera.prototype.addToScene = function(scene) { PointerCamera.prototype.addToScene = function(scene) {
scene.add(this); 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) { PointerCamera.prototype.onKeyEvent = function(event, toSet) {
// Create copy of state // Create copy of state
var motionJsonCopy = JSON.stringify(this.motion); var motionJsonCopy = JSON.stringify(this.motion);
@ -365,14 +525,26 @@ PointerCamera.prototype.onKeyEvent = function(event, toSet) {
} }
} }
/**
* Manages the key pressed events
* @param {event} event the event to manage
*/
PointerCamera.prototype.onKeyDown = function(event) { PointerCamera.prototype.onKeyDown = function(event) {
this.onKeyEvent(event, true); this.onKeyEvent(event, true);
} }
/**
* Manages the key released events
* @param {event} event the event to manage
*/
PointerCamera.prototype.onKeyUp = function(event) { PointerCamera.prototype.onKeyUp = function(event) {
this.onKeyEvent(event, false); 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) { PointerCamera.prototype.onMouseDown = function(event) {
if (!this.shouldLock) { if (!this.shouldLock) {
this.mouse.x = ( ( event.clientX - this.renderer.domElement.offsetLeft ) / this.renderer.domElement.width ) * 2 - 1; this.mouse.x = ( ( event.clientX - this.renderer.domElement.offsetLeft ) / this.renderer.domElement.width ) * 2 - 1;
@ -383,6 +555,10 @@ PointerCamera.prototype.onMouseDown = function(event) {
} }
} }
/**
* 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) { PointerCamera.prototype.onMouseMove = function(event) {
if (!this.shouldLock && this.dragging) { if (!this.shouldLock && this.dragging) {
var mouse = {x: this.mouse.x, y: this.mouse.y}; var mouse = {x: this.mouse.x, y: this.mouse.y};
@ -395,6 +571,10 @@ PointerCamera.prototype.onMouseMove = function(event) {
} }
} }
/**
* Manages the mouse move envent in case of pointer lock
* @param {event} event the event to manage
*/
PointerCamera.prototype.onMouseMovePointer = function(e) { PointerCamera.prototype.onMouseMovePointer = function(e) {
if (this.pointerLocked) { if (this.pointerLocked) {
@ -410,6 +590,10 @@ PointerCamera.prototype.onMouseMovePointer = function(e) {
} }
/**
* Manages the mouse up event. Stops the dragging
* @param {event} event the event to manage
*/
PointerCamera.prototype.onMouseUp = function(event) { PointerCamera.prototype.onMouseUp = function(event) {
this.onMouseMove(event); this.onMouseMove(event);
@ -423,11 +607,17 @@ PointerCamera.prototype.onMouseUp = function(event) {
this.dragging = false; this.dragging = false;
} }
/**
* Logs the camera to the terminal (pratical to create recommended views)
*/
PointerCamera.prototype.log = function() { PointerCamera.prototype.log = function() {
console.log("createCamera(\nnew THREE.Vector3(" + this.position.x + "," + this.position.y + ',' + this.position.z + '),\n' 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)'); + "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() { PointerCamera.prototype.save = function() {
var backup = {}; var backup = {};
backup.position = this.position.clone(); backup.position = this.position.clone();
@ -435,6 +625,9 @@ PointerCamera.prototype.save = function() {
this.history.addState(backup); this.history.addState(backup);
} }
/**
* Undo last motion according to the history
*/
PointerCamera.prototype.undo = function() { PointerCamera.prototype.undo = function() {
var move = this.history.undo(); var move = this.history.undo();
if (move !== undefined) { if (move !== undefined) {
@ -447,6 +640,9 @@ PointerCamera.prototype.undo = function() {
} }
} }
/**
* Redo last motion according to the history
*/
PointerCamera.prototype.redo = function() { PointerCamera.prototype.redo = function() {
var move = this.history.redo(); var move = this.history.redo();
if (move !== undefined) { if (move !== undefined) {
@ -459,48 +655,19 @@ PointerCamera.prototype.redo = function() {
} }
} }
/**
* Checks if there is a undo possibility in the history
* @returns {Boolean} true if undo is possible, false otherwise
*/
PointerCamera.prototype.undoable = function() { PointerCamera.prototype.undoable = function() {
return this.history.undoable(); 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() { PointerCamera.prototype.redoable = function() {
return this.history.redoable(); return this.history.redoable();
} }
var History = function() {
this.states = new Array();
this.index = -1;
this.size = 0;
}
History.prototype.addState = function(state) {
++this.index;
this.size = this.index + 1;
this.states[this.size-1] = state;
}
History.prototype.undo = function() {
if (this.undoable()) {
this.index--;
return this.currentState();
}
}
History.prototype.redo = function() {
if (this.redoable()) {
this.index++;
return this.currentState();
}
}
History.prototype.undoable = function() {
return this.index > 0;
}
History.prototype.redoable = function() {
return this.index < this.size - 1;
}
History.prototype.currentState = function() {
return this.states[this.index];
}

View File

@ -1,3 +1,7 @@
/**
* Parse a list as it is sent by the server and gives a slightly more comprehensible result
* @private
*/
var _parseList2 = function(arr) { var _parseList2 = function(arr) {
var ret = {}; var ret = {};
@ -64,37 +68,118 @@ var _parseList2 = function(arr) {
return ret; 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) { var ProgressiveLoaderGeometry = function(path, scene, camera, callback) {
// Init attributes /**
* Path to the .obj file
* @type {string}
*/
this.objPath = path; this.objPath = path;
/**
* Path to the folder where the textures are
* @type {string}
*/
this.texturesPath = path.substring(0, path.lastIndexOf('/')) + '/'; this.texturesPath = path.substring(0, path.lastIndexOf('/')) + '/';
/**
* Path to the .mtl file
* @type {string}
*/
this.mtlPath = path.replace('.obj', '.mtl'); this.mtlPath = path.replace('.obj', '.mtl');
/**
* Reference to the scene in which the object should be added
*/
this.scene = scene; this.scene = scene;
/**
* Callback to call on the object when they're created
*/
this.callback = callback; this.callback = callback;
/**
* Counter (not used)
* @private
*/
this.counter = 0; this.counter = 0;
/**
* Group where the sub-objects will be added
* @type {THREE.Object3D}
*/
this.obj = new THREE.Object3D(); this.obj = new THREE.Object3D();
scene.add(this.obj); scene.add(this.obj);
/**
* Array of the vertices of the mesh
* @type {THREE.Vector3[]}
*/
this.vertices = []; this.vertices = [];
/**
* Array of the texture coordinates of the mesh
* @type {THREE.Vector2[]}
*/
this.texCoords = []; this.texCoords = [];
/**
* Array of the normal of the mesh
* @type {THREE.Vector3[]}
*/
this.normals = []; 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 = []; this.uvs = [];
/**
* Array of all the meshes that will be added to the main object
* @type {THREE.Mesh[]}
*/
this.meshes = []; this.meshes = [];
// Init MTLLoader /**
* Loader for the material file
* @type {THREE.MTLLoader}
*/
this.loader = new THREE.MTLLoader(this.texturesPath); this.loader = new THREE.MTLLoader(this.texturesPath);
// Init io stuff /**
* Socket to connect to get the mesh
* @type {socket}
*/
this.socket = io(); this.socket = io();
this.initIOCallbacks(); this.initIOCallbacks();
/**
* Reference to the camera
* @type {PointerCamera}
*/
this.camera = camera; this.camera = camera;
} }
/**
* Starts the loading of the mesh
*/
ProgressiveLoaderGeometry.prototype.load = function() { ProgressiveLoaderGeometry.prototype.load = function() {
var self = this; var self = this;
@ -110,6 +195,9 @@ ProgressiveLoaderGeometry.prototype.load = function() {
}); });
} }
/**
* Will return a list representation of the camera (to be sent to the server)
*/
ProgressiveLoaderGeometry.prototype.getCamera = function() { ProgressiveLoaderGeometry.prototype.getCamera = function() {
if (this.camera === null) if (this.camera === null)
return null; return null;
@ -118,6 +206,9 @@ ProgressiveLoaderGeometry.prototype.getCamera = function() {
this.camera.target.x, this.camera.target.y, this.camera.target.z]; this.camera.target.x, this.camera.target.y, this.camera.target.z];
} }
/**
* Initializes the socket.io functions so that it can discuss with the server
*/
ProgressiveLoaderGeometry.prototype.initIOCallbacks = function() { ProgressiveLoaderGeometry.prototype.initIOCallbacks = function() {
var self = this; var self = this;
@ -268,6 +359,9 @@ ProgressiveLoaderGeometry.prototype.initIOCallbacks = function() {
}); });
} }
/**
* Starts the communication with the server
*/
ProgressiveLoaderGeometry.prototype.start = function() { ProgressiveLoaderGeometry.prototype.start = function() {
this.socket.emit('request', this.objPath); this.socket.emit('request', this.objPath);
} }

View File

@ -1 +0,0 @@
static_path = "/static/";

35133
js/three.js

File diff suppressed because one or more lines are too long