Should work but seems slow
This commit is contained in:
parent
5e0a6c3121
commit
844982e552
|
@ -7,7 +7,6 @@ let height = Math.floor(768 /10);
|
|||
let XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;
|
||||
let THREE = require('three');
|
||||
let L3D = require('../../static/js/l3d.min.js');
|
||||
let math = require('mathjs');
|
||||
let fs = require('fs');
|
||||
|
||||
let scene = new THREE.Scene();
|
||||
|
|
|
@ -22,6 +22,10 @@ L3D.ReplayCamera = function() {
|
|||
this.theta = Math.PI;
|
||||
this.phi = Math.PI;
|
||||
|
||||
this.shouldRecover = false;
|
||||
|
||||
this.recommendationClicked = null;
|
||||
|
||||
};
|
||||
L3D.ReplayCamera.prototype = Object.create(THREE.PerspectiveCamera.prototype);
|
||||
L3D.ReplayCamera.prototype.constructor = L3D.ReplayCamera;
|
||||
|
@ -71,11 +75,18 @@ L3D.ReplayCamera.prototype.cameraMotion = function(time) {
|
|||
var tmp = L3D.Tools.sum(L3D.Tools.mul(this.oldPosition, 1-this.t), L3D.Tools.mul(this.newPosition, this.t));
|
||||
this.position.copy(tmp);
|
||||
this.target = L3D.Tools.sum(L3D.Tools.mul(this.oldTarget, 1-this.t), L3D.Tools.mul(this.newTarget, this.t));
|
||||
this.t += 1 / (((new Date(this.path[this.counter].time)).getTime() - (new Date(this.path[this.counter-1].time)).getTime()) / 20);
|
||||
this.t += this.recovering ? 0.01 : 1 / (((new Date(this.path[this.counter].time)).getTime() - (new Date(this.path[this.counter-1].time)).getTime()) / 20);
|
||||
|
||||
if (this.t > 1) {
|
||||
this.recommendationClicked = null;
|
||||
if (typeof this.recoverCallback === 'function') {
|
||||
this.recoverCallback();
|
||||
this.recoverCallback = null;
|
||||
} else {
|
||||
this.nextEvent();
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
L3D.ReplayCamera.prototype.hermiteMotion = function(time) {
|
||||
|
@ -87,11 +98,15 @@ L3D.ReplayCamera.prototype.hermiteMotion = function(time) {
|
|||
this.t += 0.01 * time / 20;
|
||||
|
||||
if (this.t > 1) {
|
||||
this.recommendationClicked = null;
|
||||
this.nextEvent();
|
||||
}
|
||||
};
|
||||
|
||||
L3D.ReplayCamera.prototype.nextEvent = function() {
|
||||
|
||||
var self = this;
|
||||
|
||||
this.counter++;
|
||||
|
||||
// Finished
|
||||
|
@ -124,7 +139,22 @@ L3D.ReplayCamera.prototype.nextEvent = function() {
|
|||
// },500);
|
||||
// })(this);
|
||||
} else if (this.event.type == 'arrow') {
|
||||
this.moveHermite(this.cameras[this.event.id]);
|
||||
if (this.shouldRecover) {
|
||||
(function(self, tmp) {
|
||||
self.event.type = 'camera';
|
||||
self.recovering = true;
|
||||
self.move({
|
||||
position: self.position.clone(),
|
||||
target: self.cameras[self.event.id].camera.position.clone()
|
||||
}, function() {
|
||||
self.recovering = false;
|
||||
self.event.type = 'arrow';
|
||||
self.moveReco(tmp);
|
||||
});
|
||||
})(this, this.event.id);
|
||||
} else {
|
||||
this.moveReco(this.event.id);
|
||||
}
|
||||
} else if (this.event.type == 'reset') {
|
||||
this.reset();
|
||||
this.nextEvent();
|
||||
|
@ -176,7 +206,13 @@ L3D.ReplayCamera.prototype.anglesFromVectors = function() {
|
|||
this.theta = Math.atan2(forward.x, forward.z);
|
||||
};
|
||||
|
||||
L3D.ReplayCamera.prototype.move = function(recommendation) {
|
||||
L3D.ReplayCamera.prototype.move = function(recommendation, callback) {
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
|
||||
this.recoverCallback = callback;
|
||||
|
||||
}
|
||||
|
||||
var otherCamera = recommendation.camera || recommendation;
|
||||
|
||||
|
@ -185,12 +221,17 @@ L3D.ReplayCamera.prototype.move = function(recommendation) {
|
|||
this.oldPosition = this.position.clone();
|
||||
this.newTarget = new THREE.Vector3(otherCamera.target.x, otherCamera.target.y, otherCamera.target.z);
|
||||
this.newPosition = new THREE.Vector3(otherCamera.position.x, otherCamera.position.y, otherCamera.position.z);
|
||||
|
||||
this.t = 0;
|
||||
|
||||
};
|
||||
|
||||
L3D.ReplayCamera.prototype.moveHermite = function(recommendation) {
|
||||
|
||||
if (this.shouldRecover === false) {
|
||||
this.shouldRecover = true;
|
||||
}
|
||||
|
||||
var otherCamera = recommendation.camera || recommendation;
|
||||
|
||||
this.movingHermite = true;
|
||||
|
@ -209,6 +250,14 @@ L3D.ReplayCamera.prototype.moveHermite = function(recommendation) {
|
|||
);
|
||||
};
|
||||
|
||||
L3D.ReplayCamera.prototype.moveReco = function(recommendationId) {
|
||||
|
||||
this.recommendationClicked = this.cameras[recommendationId].camera;
|
||||
|
||||
this.moveHermite(this.cameras[recommendationId]);
|
||||
|
||||
};
|
||||
|
||||
L3D.ReplayCamera.prototype.save = function() {};
|
||||
|
||||
/**
|
||||
|
@ -220,18 +269,23 @@ L3D.ReplayCamera.prototype.save = function() {};
|
|||
* </ol>
|
||||
*/
|
||||
L3D.ReplayCamera.prototype.toList = function() {
|
||||
this.updateMatrix();
|
||||
this.updateMatrixWorld();
|
||||
|
||||
var camera = (this.recommendationClicked === null ? this : this.recommendationClicked);
|
||||
|
||||
camera.updateMatrix();
|
||||
camera.updateMatrixWorld();
|
||||
|
||||
var frustum = new THREE.Frustum();
|
||||
var projScreenMatrix = new THREE.Matrix4();
|
||||
projScreenMatrix.multiplyMatrices(this.projectionMatrix, this.matrixWorldInverse);
|
||||
projScreenMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
|
||||
|
||||
frustum.setFromMatrix(new THREE.Matrix4().multiplyMatrices(this.projectionMatrix, this.matrixWorldInverse));
|
||||
frustum.setFromMatrix(new THREE.Matrix4().multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse));
|
||||
|
||||
var ret =
|
||||
[[this.position.x, this.position.y, this.position.z],
|
||||
[this.target.x, this.target.y, this.target.z]];
|
||||
[[camera.position.x, camera.position.y, camera.position.z],
|
||||
[camera.target.x, camera.target.y, camera.target.z],
|
||||
this.recommendationClicked !== null
|
||||
];
|
||||
|
||||
for (var i = 0; i < frustum.planes.length; i++) {
|
||||
|
||||
|
|
|
@ -90,6 +90,8 @@ var _parseList = function(arr) {
|
|||
*/
|
||||
var ProgressiveLoader = function(path, scene, camera, callback, log, laggy) {
|
||||
|
||||
var self = this;
|
||||
|
||||
/**
|
||||
* Path to the .obj file
|
||||
* @type {string}
|
||||
|
@ -184,6 +186,12 @@ var ProgressiveLoader = function(path, scene, camera, callback, log, laggy) {
|
|||
*/
|
||||
this.camera = camera;
|
||||
|
||||
this.camera._moveReco = this.camera.moveReco;
|
||||
|
||||
this.camera.moveReco = function(param) {
|
||||
self.socket.emit('reco', param);
|
||||
self.camera._moveReco.apply(self.camera, arguments);
|
||||
};
|
||||
|
||||
/**
|
||||
* Number of total elements for loading
|
||||
|
@ -210,6 +218,14 @@ var ProgressiveLoader = function(path, scene, camera, callback, log, laggy) {
|
|||
*/
|
||||
this.log = log;
|
||||
|
||||
this.mapFace = {};
|
||||
|
||||
};
|
||||
|
||||
ProgressiveLoader.prototype.hasFace = function(face) {
|
||||
|
||||
return this.mapFace[(face.a) + '-' + (face.b) + '-' + (face.c)] === true;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -376,6 +392,8 @@ ProgressiveLoader.prototype.initIOCallbacks = function() {
|
|||
|
||||
}
|
||||
|
||||
self.mapFace[elt.a + '-' + elt.b + '-' + elt.c] = true;
|
||||
|
||||
|
||||
} else if (elt.type === 'global') {
|
||||
|
||||
|
@ -386,6 +404,10 @@ ProgressiveLoader.prototype.initIOCallbacks = function() {
|
|||
|
||||
}
|
||||
|
||||
if (typeof self.onBeforeEmit === 'function') {
|
||||
self.onBeforeEmit();
|
||||
}
|
||||
|
||||
// Ask for next elements
|
||||
if (!self.laggy) {
|
||||
self.socket.emit('next', self.getCamera());
|
||||
|
@ -396,7 +418,7 @@ ProgressiveLoader.prototype.initIOCallbacks = function() {
|
|||
|
||||
this.socket.on('disconnect', function() {
|
||||
if (typeof self.log === 'function')
|
||||
self.log(self.numberOfFacesReceived, self.numberOfFaces);
|
||||
self.log(self.numberOfFaces, self.numberOfFaces);
|
||||
self.finished = true;
|
||||
|
||||
if (typeof L3D.ProgressiveLoader.onFinished === 'function') {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
L3D.ArrowRecommendation = function(arg1, arg2, arg3, arg4, position, target) {
|
||||
|
||||
L3D.BaseRecommendation.apply(this);
|
||||
L3D.BaseRecommendation.apply(this, arguments);
|
||||
|
||||
/**
|
||||
* @type {L3D.FixedCamera}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
L3D.BaseRecommendation = function() {
|
||||
|
||||
THREE.Object3D.apply(this);
|
||||
THREE.Object3D.apply(this, arguments);
|
||||
|
||||
this.camera = new THREE.PerspectiveCamera();
|
||||
this.camera.position.copy(arguments[4]);
|
||||
|
|
|
@ -712,11 +712,27 @@ L3D.initSponzaScene = function(scene, collidableObjects, recommendation, clickab
|
|||
|
||||
};
|
||||
|
||||
L3D.createSponzaCoins = function() {
|
||||
return [];
|
||||
L3D.createSponzaRecommendations = function(width, height) {
|
||||
var createRecommendation = function(position, target) {
|
||||
return new Recommendation(
|
||||
50,
|
||||
width / height,
|
||||
1,
|
||||
100000,
|
||||
position,
|
||||
target
|
||||
);
|
||||
};
|
||||
|
||||
L3D.createSponzaRecommendations = function() {
|
||||
return [
|
||||
createRecommendation(
|
||||
new THREE.Vector3(97.36225946503932,10.925697484337014,12.852363038244272),
|
||||
new THREE.Vector3(133.315101552449,18.576354168001703,-2.9229530646577633)
|
||||
)
|
||||
];
|
||||
};
|
||||
|
||||
L3D.createSponzaCoins = function() {
|
||||
return [];
|
||||
};
|
||||
|
||||
|
|
|
@ -316,7 +316,8 @@ var availableMeshNames = {
|
|||
},
|
||||
|
||||
'/static/data/sponza/sponza.obj': {
|
||||
done: false
|
||||
done: false,
|
||||
recommendations : L3D.createSponzaRecommendations(1134,768)
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -361,7 +362,8 @@ function pushMesh(name) {
|
|||
|
||||
geo.availableMeshes[name].recommendations.push({
|
||||
position: reco.position,
|
||||
frustum: frustum.planes
|
||||
target: reco.target,
|
||||
planes: frustum.planes
|
||||
});
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,19 @@
|
|||
var fs = require('fs');
|
||||
var THREE = require('three');
|
||||
var L3D = require('../../static/js/l3d.min.js');
|
||||
|
||||
try
|
||||
{
|
||||
var predictionTables = [
|
||||
JSON.parse(fs.readFileSync('./mat1.json')),
|
||||
JSON.parse(fs.readFileSync('./mat2.json')),
|
||||
JSON.parse(fs.readFileSync('./mat3.json'))
|
||||
];
|
||||
} catch (e) {
|
||||
process.stderr.write('No prefetching will be done !');
|
||||
predictionTables = [];
|
||||
}
|
||||
|
||||
function isInFrustum(element, planes) {
|
||||
|
||||
if (element instanceof Array) {
|
||||
|
@ -143,7 +156,9 @@ geo.MeshStreamer = function(path) {
|
|||
* Number of element to send by packet
|
||||
* @type {Number}
|
||||
*/
|
||||
this.chunk = 1000;
|
||||
this.chunk = 500;
|
||||
|
||||
this.previousReco = 0;
|
||||
|
||||
if (path !== undefined) {
|
||||
|
||||
|
@ -155,7 +170,18 @@ geo.MeshStreamer = function(path) {
|
|||
|
||||
geo.MeshStreamer.prototype.isBackFace = function(camera, face) {
|
||||
|
||||
var directionCamera = L3D.Tools.diff(camera.target, camera.position);
|
||||
var directionCamera = L3D.Tools.diff(
|
||||
L3D.Tools.mul(
|
||||
L3D.Tools.sum(
|
||||
L3D.Tools.sum(
|
||||
this.mesh.vertices[face.a],
|
||||
this.mesh.vertices[face.b]
|
||||
),
|
||||
this.mesh.vertices[face.c]
|
||||
),
|
||||
1/3),
|
||||
camera.position
|
||||
);
|
||||
|
||||
var v1 = L3D.Tools.diff(this.mesh.vertices[face.b], this.mesh.vertices[face.a]);
|
||||
var v2 = L3D.Tools.diff(this.mesh.vertices[face.c], this.mesh.vertices[face.a]);
|
||||
|
@ -260,6 +286,21 @@ geo.MeshStreamer.prototype.start = function(socket) {
|
|||
|
||||
self.mesh = geo.availableMeshes[path];
|
||||
|
||||
switch (path) {
|
||||
case '/static/data/bobomb/bobomb battlefeild.obj':
|
||||
case '/static/data/bobomb/bobomb battlefeild_sub.obj':
|
||||
self.predictionTable = predictionTables[0];
|
||||
break;
|
||||
case '/static/data/mountain/coocoolmountain.obj':
|
||||
case '/static/data/mountain/coocoolmountain_sub.obj':
|
||||
self.predictionTable = predictionTables[1];
|
||||
break;
|
||||
case '/static/data/whomp/Whomps Fortress.obj':
|
||||
case '/static/data/whomp/Whomps Fortress_sub.obj':
|
||||
self.predictionTable = predictionTables[2];
|
||||
break;
|
||||
};
|
||||
|
||||
if (self.mesh === undefined) {
|
||||
process.stderr.write('Wrong path for model : ' + path);
|
||||
socket.emit('refused');
|
||||
|
@ -290,16 +331,102 @@ geo.MeshStreamer.prototype.start = function(socket) {
|
|||
|
||||
});
|
||||
|
||||
socket.on('next', function(camera) {
|
||||
socket.on('reco', function(recoId) {
|
||||
|
||||
self.previousReco = recoId + 1;
|
||||
|
||||
});
|
||||
|
||||
socket.on('next', function(_camera) {
|
||||
|
||||
var cameraFrustum = {};
|
||||
|
||||
// Clean camera attribute
|
||||
if (_camera !== null) {
|
||||
|
||||
cameraFrustum = {
|
||||
position: {
|
||||
x: _camera[0][0],
|
||||
y: _camera[0][1],
|
||||
z: _camera[0][2]
|
||||
},
|
||||
target: {
|
||||
x: _camera[1][0],
|
||||
y: _camera[1][1],
|
||||
z: _camera[1][2]
|
||||
},
|
||||
planes: []
|
||||
};
|
||||
|
||||
var shouldPrefetch = _camera[2];
|
||||
|
||||
for (i = 3; i < _camera.length; i++) {
|
||||
|
||||
cameraFrustum.planes.push({
|
||||
normal: {
|
||||
x: _camera[i][0],
|
||||
y: _camera[i][1],
|
||||
z: _camera[i][2]
|
||||
},
|
||||
constant: _camera[i][3]
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Find best recommendation
|
||||
var bestReco;
|
||||
var bestScore = -Infinity;
|
||||
var bestIndex = null;
|
||||
|
||||
|
||||
if (self.predictionTable !== undefined) {
|
||||
|
||||
for (var i = 0; i < self.mesh.recommendations.length; i++) {
|
||||
|
||||
if (self.predictionTable[self.previousReco][i+1] > bestScore) {
|
||||
|
||||
bestReco = self.mesh.recommendations[i];
|
||||
bestScore = self.predictionTable[self.previousReco][i+1];
|
||||
bestIndex = i;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// For sponza
|
||||
bestReco = self.mesh.recommendations[0];
|
||||
|
||||
}
|
||||
|
||||
// Create config for proportions of chunks
|
||||
var config = [];
|
||||
|
||||
if (shouldPrefetch) {
|
||||
|
||||
// Camera cull
|
||||
config.push({
|
||||
proportion: 0.5,
|
||||
frustum: cameraFrustum
|
||||
});
|
||||
|
||||
config.push({
|
||||
proportion: 0.5,
|
||||
frustum: bestReco
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// Send next elements
|
||||
var next = self.nextElements(camera);
|
||||
var next = self.nextElements(config);
|
||||
|
||||
if (next.data.length === 0) {
|
||||
|
||||
// If nothing, just serve stuff
|
||||
var tmp = self.nextElements(camera, true);
|
||||
var tmp = self.nextElements();
|
||||
next.data = tmp.data;
|
||||
|
||||
}
|
||||
|
@ -352,59 +479,10 @@ geo.MeshStreamer.prototype.nextMaterials = function() {
|
|||
* only interesting parts according to the camera
|
||||
* @returns {array} an array of elements ready to send
|
||||
*/
|
||||
geo.MeshStreamer.prototype.nextElements = function(_camera, force) {
|
||||
geo.MeshStreamer.prototype.nextElements = function(config) {
|
||||
|
||||
var i;
|
||||
|
||||
if (force === undefined) {
|
||||
|
||||
force = false;
|
||||
|
||||
}
|
||||
|
||||
// Prepare camera (and scale to model)
|
||||
var camera = null;
|
||||
var planes = [];
|
||||
var direction;
|
||||
|
||||
if (_camera !== null) {
|
||||
|
||||
camera = {
|
||||
position: {
|
||||
x: _camera[0][0],
|
||||
y: _camera[0][1],
|
||||
z: _camera[0][2]
|
||||
},
|
||||
target: {
|
||||
x: _camera[1][0],
|
||||
y: _camera[1][1],
|
||||
z: _camera[1][2]
|
||||
}
|
||||
};
|
||||
|
||||
for (i = 2; i < _camera.length; i++) {
|
||||
|
||||
planes.push({
|
||||
normal: {
|
||||
x: _camera[i][0],
|
||||
y: _camera[i][1],
|
||||
z: _camera[i][2]
|
||||
},
|
||||
constant: _camera[i][3]
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// Compute camera direction
|
||||
direction = {
|
||||
x: camera.target.x - camera.position.x,
|
||||
y: camera.target.y - camera.position.y,
|
||||
z: camera.target.z - camera.position.z
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
var sent = 0;
|
||||
var data = [];
|
||||
|
||||
var mightBeCompletetlyFinished = true;
|
||||
|
@ -413,6 +491,21 @@ geo.MeshStreamer.prototype.nextElements = function(_camera, force) {
|
|||
// if (camera != null)
|
||||
// this.mesh.faces.sort(this.faceComparator(camera));
|
||||
|
||||
if (config === undefined) { config = [] }
|
||||
|
||||
configloop:
|
||||
for (var configIndex = 0; configIndex < config.length + 1; configIndex++) {
|
||||
|
||||
var sent = 0;
|
||||
|
||||
// config[0] should always be cameraFrustum, with eventually 0 proportion
|
||||
var currentConfig = configIndex !== config.length ? config[configIndex] : config[0];
|
||||
if (currentConfig === undefined) {
|
||||
currentConfig = {
|
||||
proportion : Infinity,
|
||||
}
|
||||
}
|
||||
|
||||
for (var faceIndex = 0; faceIndex < this.mesh.faces.length; faceIndex++) {
|
||||
|
||||
var currentFace = this.mesh.faces[faceIndex];
|
||||
|
@ -429,19 +522,19 @@ geo.MeshStreamer.prototype.nextElements = function(_camera, force) {
|
|||
var vertex2 = this.mesh.vertices[currentFace.b];
|
||||
var vertex3 = this.mesh.vertices[currentFace.c];
|
||||
|
||||
if (!force && camera !== null) {
|
||||
if (currentConfig.frustum !== undefined) {
|
||||
|
||||
var display = false;
|
||||
var exitToContinue = false;
|
||||
threeVertices = [vertex1, vertex2, vertex3];
|
||||
|
||||
// Frustum culling
|
||||
if (!isInFrustum(threeVertices, planes)) {
|
||||
if (!isInFrustum(threeVertices, currentConfig.frustum.planes)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Backface culling
|
||||
if (this.isBackFace(camera, currentFace)) {
|
||||
if (this.isBackFace(currentConfig.frustum, currentFace)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -535,11 +628,23 @@ geo.MeshStreamer.prototype.nextElements = function(_camera, force) {
|
|||
|
||||
sent++;
|
||||
|
||||
if (sent > this.chunk) {
|
||||
if (data.length > this.chunk) {
|
||||
|
||||
return {data: data, finished: false};
|
||||
// console.log(configIndex, sent/(this.chunk * currentConfig.proportion));
|
||||
return {data: data, finsihed:false};
|
||||
|
||||
}
|
||||
|
||||
if (sent > this.chunk * currentConfig.proportion) {
|
||||
|
||||
// console.log(configIndex, sent/(this.chunk * currentConfig.proportion));
|
||||
continue configloop;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return {data: data, finished: mightBeCompletetlyFinished};
|
||||
}
|
||||
|
||||
return {data: data, finished: mightBeCompletetlyFinished};
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
let fs = require('fs');
|
||||
let THREE = require('three');
|
||||
let L3D = require('../static/js/l3d.min.js');
|
||||
let L3D = require('../../static/js/l3d.min.js');
|
||||
|
||||
function serialize(object) {
|
||||
|
||||
|
|
Loading…
Reference in New Issue