Changed stuff and added doc
This commit is contained in:
parent
6242e6f122
commit
5e445a8c28
19
README.md
19
README.md
|
@ -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,33 +19,33 @@ 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
|
||||||
```
|
```
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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:
|
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 \
|
||||||
|
|
|
@ -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];
|
|
||||||
}
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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