Changed stuff and added doc
This commit is contained in:
parent
6242e6f122
commit
5e445a8c28
15
README.md
15
README.md
|
@ -5,13 +5,12 @@ models written with Node.js.
|
|||
It is hosted by [OpenShift](https://www.openshift.com/) at
|
||||
[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
|
||||
where you want, and you can initialize it by running the script
|
||||
`sql/backup.pgsql`.
|
||||
|
||||
### Nodejs configuration
|
||||
## Nodejs configuration
|
||||
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 :
|
||||
|
||||
|
@ -20,21 +19,21 @@ module.exports.url = ... // the url to connect to your database
|
|||
|
||||
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 :
|
||||
|
||||
- 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
|
||||
[closure-compiler](https://github.com/google/closure-compiler)
|
||||
|
||||
#### Compiling without minifying
|
||||
### Compiling without minifying
|
||||
To compile without minifying, simply run
|
||||
```
|
||||
make
|
||||
```
|
||||
in `static/js`.
|
||||
|
||||
#### Compiling and minifying
|
||||
### Compiling and minifying
|
||||
To compile and minify the js files, you have to run
|
||||
```
|
||||
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`
|
||||
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.
|
||||
|
||||
### Running the server
|
||||
## Running the server
|
||||
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
|
||||
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
var fs = require('fs');
|
||||
var mesh = require('./Mesh.js');
|
||||
|
||||
/**
|
||||
* @namespace
|
||||
*/
|
||||
var geo = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
function bisect(items, x, lo, hi) {
|
||||
var mid;
|
||||
if (typeof(lo) == 'undefined') lo = 0;
|
||||
|
@ -15,10 +21,16 @@ function bisect(items, x, lo, hi) {
|
|||
return lo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
function insort(items, x) {
|
||||
items.splice(bisect(items, x), 0, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
function partialSort(items, k, comparator) {
|
||||
var smallest = items.slice(0, k).sort(),
|
||||
max = smallest[k-1];
|
||||
|
@ -35,18 +47,54 @@ function partialSort(items, k, comparator) {
|
|||
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) {
|
||||
// Different parts of a obj (a mesh per material)
|
||||
/**
|
||||
* array of each part of the mesh
|
||||
* @type {mesh.Mesh[]}
|
||||
*/
|
||||
this.meshes = [];
|
||||
|
||||
// In meshes, vertices and texture coords are shared
|
||||
/**
|
||||
* array of the vertices of the meshes (all merged)
|
||||
* @type {mesh.Vertex[]}
|
||||
*/
|
||||
this.vertices = [];
|
||||
|
||||
/**
|
||||
* array of the faces of the meshes (all merged)
|
||||
* @type {mesh.Face[]}
|
||||
*/
|
||||
this.faces = [];
|
||||
|
||||
/**
|
||||
* array of the normals of the meshes (all merged)
|
||||
* @type {mesh.Normal[]}
|
||||
*/
|
||||
this.normals = [];
|
||||
|
||||
/**
|
||||
* array of the texture coordinates (all merged)
|
||||
* @type {mesh.TexCoord[]}
|
||||
*/
|
||||
this.texCoords = [];
|
||||
|
||||
/**
|
||||
* array of the faces in a nice order for sending
|
||||
* @type {mesh.Face[]}
|
||||
*/
|
||||
this.orderedFaces = [];
|
||||
|
||||
// Chunk size
|
||||
/**
|
||||
* Number of element to send by packet
|
||||
* @type {Number}
|
||||
*/
|
||||
this.chunk = 1000;
|
||||
|
||||
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) {
|
||||
|
||||
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) {
|
||||
var self = this;
|
||||
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) {
|
||||
|
||||
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() {
|
||||
|
||||
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) {
|
||||
|
||||
// Prepare camera (and scale to model)
|
||||
|
|
|
@ -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];
|
||||
}
|
|
@ -70,6 +70,7 @@ StreamingSimulator:
|
|||
|
||||
PrototypeTools:
|
||||
$(CLOSURE) $(OPT) \
|
||||
--js History.js \
|
||||
--js StaticPath.js \
|
||||
--js Hermite.js \
|
||||
--js Camera.js \
|
||||
|
|
|
@ -1,7 +1,15 @@
|
|||
// class camera extends THREE.PerspectiveCamera
|
||||
/**
|
||||
* 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)
|
||||
|
@ -9,38 +17,118 @@ var PointerCamera = function() {
|
|||
else
|
||||
listenerTarget = arguments[5];
|
||||
|
||||
// Set Position
|
||||
/**
|
||||
* Theta angle of the camera
|
||||
* @type {Number}
|
||||
*/
|
||||
this.theta = Math.PI;
|
||||
|
||||
/**
|
||||
* Phi angle of the camera
|
||||
* @type {Number}
|
||||
*/
|
||||
this.phi = Math.PI;
|
||||
|
||||
// this.keyboard = undefined;
|
||||
/**
|
||||
* 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};
|
||||
|
||||
|
||||
// Stuff for rendering
|
||||
/**
|
||||
* 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);
|
||||
|
||||
// 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 = {};
|
||||
|
||||
/**
|
||||
* Sentitivity of the mouse
|
||||
* @type {Number}
|
||||
*/
|
||||
this.sensitivity = 0.05;
|
||||
|
||||
/**
|
||||
* Speed of the camera
|
||||
* @type {Number}
|
||||
*/
|
||||
this.speed = 1;
|
||||
|
||||
// Raycaster for collisions
|
||||
/**
|
||||
* Raycaster used to compute collisions
|
||||
* @type {THREE.Raycaster}
|
||||
*/
|
||||
this.raycaster = new THREE.Raycaster();
|
||||
|
||||
// Create history object
|
||||
/**
|
||||
* History of the moves of the camera
|
||||
* @type {History}
|
||||
*/
|
||||
this.history = new History();
|
||||
|
||||
// Variable for lock pointer
|
||||
/**
|
||||
* 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;
|
||||
|
||||
// Set events from the document
|
||||
|
@ -66,15 +154,32 @@ var PointerCamera = function() {
|
|||
// listenerTarget.addEventListener('mouseup', function() { console.log("mouseup");}, 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) {
|
||||
|
@ -97,6 +202,9 @@ PointerCamera.prototype.lockPointer = function() {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the camera when the pointer lock changes state
|
||||
*/
|
||||
PointerCamera.prototype.onPointerLockChange = function() {
|
||||
|
||||
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) {
|
||||
if (this.moving) {
|
||||
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) {
|
||||
var position_direction = Tools.diff(this.new_position, this.position);
|
||||
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) {
|
||||
var eval = this.hermitePosition.eval(this.t);
|
||||
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) {
|
||||
// Update angles
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the camera to its resetElements, and finishes any motion
|
||||
*/
|
||||
PointerCamera.prototype.reset = function() {
|
||||
this.resetPosition();
|
||||
this.moving = false;
|
||||
|
@ -231,12 +357,18 @@ PointerCamera.prototype.reset = function() {
|
|||
(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);
|
||||
|
@ -248,6 +380,9 @@ PointerCamera.prototype.vectorsFromAngles = function() {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes theta and phi according to the vectors (forward, left, ...)
|
||||
*/
|
||||
PointerCamera.prototype.anglesFromVectors = function() {
|
||||
var forward = Tools.diff(this.target, this.position);
|
||||
forward.normalize();
|
||||
|
@ -259,6 +394,11 @@ PointerCamera.prototype.anglesFromVectors = function() {
|
|||
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;
|
||||
|
@ -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) {
|
||||
if (toSave === undefined)
|
||||
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) {
|
||||
this.raycaster.set(this.position, direction.clone().normalize());
|
||||
var intersects = this.raycaster.intersectObjects(this.collidableObjects, true);
|
||||
|
@ -323,15 +473,25 @@ PointerCamera.prototype.isColliding = function(direction) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Look function
|
||||
/**
|
||||
* 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);
|
||||
|
@ -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) {
|
||||
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;
|
||||
|
@ -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) {
|
||||
if (!this.shouldLock && this.dragging) {
|
||||
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) {
|
||||
|
||||
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) {
|
||||
this.onMouseMove(event);
|
||||
|
||||
|
@ -423,11 +607,17 @@ PointerCamera.prototype.onMouseUp = function(event) {
|
|||
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();
|
||||
|
@ -435,6 +625,9 @@ PointerCamera.prototype.save = function() {
|
|||
this.history.addState(backup);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undo last motion according to the history
|
||||
*/
|
||||
PointerCamera.prototype.undo = function() {
|
||||
var move = this.history.undo();
|
||||
if (move !== undefined) {
|
||||
|
@ -447,6 +640,9 @@ PointerCamera.prototype.undo = function() {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Redo last motion according to the history
|
||||
*/
|
||||
PointerCamera.prototype.redo = function() {
|
||||
var move = this.history.redo();
|
||||
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() {
|
||||
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();
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
|
|
|
@ -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 ret = {};
|
||||
|
@ -64,37 +68,118 @@ var _parseList2 = function(arr) {
|
|||
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) {
|
||||
|
||||
// Init attributes
|
||||
/**
|
||||
* 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 = [];
|
||||
|
||||
// Init MTLLoader
|
||||
/**
|
||||
* Loader for the material file
|
||||
* @type {THREE.MTLLoader}
|
||||
*/
|
||||
this.loader = new THREE.MTLLoader(this.texturesPath);
|
||||
|
||||
// Init io stuff
|
||||
/**
|
||||
* 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;
|
||||
|
@ -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() {
|
||||
if (this.camera === null)
|
||||
return null;
|
||||
|
@ -118,6 +206,9 @@ ProgressiveLoaderGeometry.prototype.getCamera = function() {
|
|||
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() {
|
||||
|
||||
var self = this;
|
||||
|
@ -268,6 +359,9 @@ ProgressiveLoaderGeometry.prototype.initIOCallbacks = function() {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the communication with the server
|
||||
*/
|
||||
ProgressiveLoaderGeometry.prototype.start = function() {
|
||||
this.socket.emit('request', this.objPath);
|
||||
}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
static_path = "/static/";
|
35133
js/three.js
35133
js/three.js
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue