From 09f6c2028f7bde0a7d46666aecebe93a33ed60d8 Mon Sep 17 00:00:00 2001 From: Thomas FORGIONE Date: Mon, 29 Jun 2015 09:50:26 +0200 Subject: [PATCH] Avoid multiple loading of same mesh (long operation) --- geo/MeshContainer.js | 169 ++++++++++++++++++++++++++++++++++ geo/MeshStreamer.js | 213 ++++++++++--------------------------------- 2 files changed, 218 insertions(+), 164 deletions(-) create mode 100644 geo/MeshContainer.js diff --git a/geo/MeshContainer.js b/geo/MeshContainer.js new file mode 100644 index 0000000..255139d --- /dev/null +++ b/geo/MeshContainer.js @@ -0,0 +1,169 @@ +var fs = require('fs'); +var mesh = require('./Mesh.js'); + +/** + * @namespace + */ +var cont = {}; + +/** + * Represents a mesh. All meshes are loaded once in cont.availableMesh to avoid + * loading at each mesh request + * @constructor + * @memberOf cont + */ +cont.MeshContainer = function(path) { + + /** + * array of each part of the mesh + * @type {mesh.Mesh[]} + */ + this.meshes = []; + + /** + * 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 = []; + + if (path !== undefined) { + + this.loadFromFile(path); + + } + +} + +/** + * Loads a obj file + * @param {string} path the path to the file + */ +cont.MeshContainer.prototype.loadFromFile = function(path) { + var self = this; + + var data = fs.readFileSync(path, {encoding: 'utf-8'}); + + var currentMesh; + + // Get lines from file + var lines = data.toString('utf-8').split("\n"); + + // For each line + for (var i = 0; i < lines.length; i++) { + + var line = lines[i]; + + if (line[0] === 'v') { + + if (line[1] === 't') { + + // Texture coord + var texCoord = new mesh.TexCoord(line); + texCoord.index = self.texCoords.length; + self.texCoords.push(texCoord); + + } else if (line[1] === 'n') { + + var normal = new mesh.Normal(line); + normal.index = self.normals.length; + self.normals.push(normal); + + } else { + + // Just a simple vertex + // if (currentMesh === undefined) { + + // // Chances are that we won't use any material in this case + // currentMesh = new mesh.Mesh(); + // self.meshes.push(currentMesh); + + // } + + var vertex = new mesh.Vertex(line); + vertex.index = self.vertices.length; + self.vertices.push(vertex); + + } + + } else if (line[0] === 'f') { + + // Create mesh if it doesn't exist + if (currentMesh === undefined) { + currentMesh = new mesh.Mesh(); + self.meshes.push(currentMesh); + } + + // Create faces (two if Face4) + var faces = currentMesh.addFaces(line); + + faces[0].index = self.faces.length; + faces[0].meshIndex = self.meshes.length - 1; + self.faces.push(faces[0]); + + if (faces.length === 2) { + + faces[1].index = self.faces.length; + faces[1].meshIndex = self.meshes.length - 1; + self.faces.push(faces[1]); + + } + + } else if (line[0] === 'u') { + + // usemtl + // If a current mesh exists, finish it + + // Create a new mesh + currentMesh = new mesh.Mesh(); + self.meshes.push(currentMesh); + currentMesh.material = (new mesh.Material(line)).name; + // console.log(currentMesh.material); + + } + + } + +} + +var availableMeshNames = [ + '/static/data/castle/princess peaches castle (outside).obj', + '/static/data/mountain/coocoolmountain.obj', + '/static/data/whomp/Whomps Fortress.obj', + '/static/data/bobomb/bobomb battlefeild.obj', + '/static/data/sponza/sponza.obj' +]; + +for (var i = 1; i < 26; i++) { + + availableMeshNames.push('/static/data/spheres/' + i + '.obj'); + +} + +cont.availableMeshes = {}; + +for (var i = 0; i < availableMeshNames.length; i++) { + + var name = availableMeshNames[i]; + cont.availableMeshes[name] = new cont.MeshContainer(name.substring(1, name.length)); + +} + +module.exports = cont; diff --git a/geo/MeshStreamer.js b/geo/MeshStreamer.js index 803b8e9..5cb0893 100644 --- a/geo/MeshStreamer.js +++ b/geo/MeshStreamer.js @@ -1,5 +1,6 @@ var fs = require('fs'); var mesh = require('./Mesh.js'); +var cont = require('./MeshContainer.js'); /** * @namespace @@ -52,45 +53,33 @@ function partialSort(items, k, comparator) { * @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) { - /** - * array of each part of the mesh - * @type {mesh.Mesh[]} - */ - this.meshes = []; +geo.MeshStreamer = function(path) { /** - * array of the vertices of the meshes (all merged) - * @type {mesh.Vertex[]} + * array of booleans telling if the ith vertex has already been sent + * @type {Boolean[]} */ this.vertices = []; /** - * array of the faces of the meshes (all merged) - * @type {mesh.Face[]} + * array of booleans telling if the ith face has already been sent + * @type {Boolean[]} */ this.faces = []; /** - * array of the normals of the meshes (all merged) - * @type {mesh.Normal[]} + * array of booleans telling if the ith normal has already been sent + * @type {Boolean[]} */ this.normals = []; /** - * array of the texture coordinates (all merged) - * @type {mesh.TexCoord[]} + * array of booleans telling if the ith texCoord has already been sent + * @type {Boolean[]} */ this.texCoords = []; - /** - * array of the faces in a nice order for sending - * @type {mesh.Face[]} - */ - this.orderedFaces = []; - /** * Number of element to send by packet * @type {Number} @@ -98,13 +87,11 @@ geo.MeshStreamer = function(path, callback) { this.chunk = 1000; if (path !== undefined) { - var self = this; - this.loadFromFile(path, function() { - if (typeof callback === 'function') - callback(); - }); + this.mesh = cont.availableMeshes[path]; + } + } /** @@ -183,108 +170,6 @@ 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) { - - var oldTime = Date.now(); - - var currentMesh; - - // Get lines from file - var lines = data.toString('utf-8').split("\n"); - - // For each line - for (var i = 0; i < lines.length; i++) { - - var line = lines[i]; - - if (line[0] === 'v') { - - if (line[1] === 't') { - - // Texture coord - var texCoord = new mesh.TexCoord(line); - texCoord.index = self.texCoords.length; - self.texCoords.push(texCoord); - - } else if (line[1] === 'n') { - - var normal = new mesh.Normal(line); - normal.index = self.normals.length; - self.normals.push(normal); - - } else { - - // Just a simple vertex - // if (currentMesh === undefined) { - - // // Chances are that we won't use any material in this case - // currentMesh = new mesh.Mesh(); - // self.meshes.push(currentMesh); - - // } - - var vertex = new mesh.Vertex(line); - vertex.index = self.vertices.length; - self.vertices.push(vertex); - - } - - } else if (line[0] === 'f') { - - // Create mesh if it doesn't exist - if (currentMesh === undefined) { - currentMesh = new mesh.Mesh(); - self.meshes.push(currentMesh); - } - - // Create faces (two if Face4) - var faces = currentMesh.addFaces(line); - - faces[0].index = self.faces.length; - faces[0].meshIndex = self.meshes.length - 1; - self.faces.push(faces[0]); - self.orderedFaces.push(faces[0]); - - if (faces.length === 2) { - - faces[1].index = self.faces.length; - faces[1].meshIndex = self.meshes.length - 1; - self.faces.push(faces[1]); - self.orderedFaces.push(faces[1]); - - } - - } else if (line[0] === 'u') { - - // usemtl - // If a current mesh exists, finish it - - // Create a new mesh - currentMesh = new mesh.Mesh(); - self.meshes.push(currentMesh); - currentMesh.material = (new mesh.Material(line)).name; - // console.log(currentMesh.material); - - } - - } - - if (typeof callback === 'function') { - callback(); - } - - console.log(Date.now() - oldTime); - - }); -} - /** * Initialize the socket.io callback * @param {socket} socket the socket to initialize @@ -299,6 +184,8 @@ geo.MeshStreamer.prototype.start = function(socket) { socket.on('request', function(path) { console.log('Asking for ' + path); + self.mesh = cont.availableMeshes[path]; + var regex = /.*\.\..*/; var filePath = path.substring(1, path.length); @@ -308,9 +195,7 @@ geo.MeshStreamer.prototype.start = function(socket) { return; } - self.loadFromFile(filePath, function() { - socket.emit('ok'); - }); + socket.emit('ok'); }); @@ -355,9 +240,9 @@ geo.MeshStreamer.prototype.nextMaterials = function() { var data = []; - for (var i = 0; i < this.meshes.length; i++) { + for (var i = 0; i < this.mesh.meshes.length; i++) { - var currentMesh = this.meshes[i]; + var currentMesh = this.mesh.meshes[i]; // Send usemtl data.push([ @@ -365,8 +250,8 @@ geo.MeshStreamer.prototype.nextMaterials = function() { currentMesh.material, currentMesh.vertices.length, currentMesh.faces.length, - this.texCoords.length > 0, - this.normals.length > 0 + this.mesh.texCoords.length > 0, + this.mesh.normals.length > 0 ]); } @@ -437,9 +322,9 @@ geo.MeshStreamer.prototype.nextElements = function(_camera, force) { // Sort faces var mightBeCompletetlyFinished = true; - for (var meshIndex = 0; meshIndex < this.meshes.length; meshIndex++) { + for (var meshIndex = 0; meshIndex < this.mesh.meshes.length; meshIndex++) { - var currentMesh = this.meshes[meshIndex]; + var currentMesh = this.mesh.meshes[meshIndex]; if (currentMesh.isFinished()) { @@ -461,9 +346,9 @@ geo.MeshStreamer.prototype.nextElements = function(_camera, force) { } - var vertex1 = this.vertices[currentFace.a]; - var vertex2 = this.vertices[currentFace.b]; - var vertex3 = this.vertices[currentFace.c]; + var vertex1 = this.mesh.vertices[currentFace.a]; + var vertex2 = this.mesh.vertices[currentFace.b]; + var vertex3 = this.mesh.vertices[currentFace.c]; // if (camera !== null) { @@ -534,82 +419,82 @@ geo.MeshStreamer.prototype.nextElements = function(_camera, force) { } - if (!vertex1.sent) { + if (!this.vertices[currentFace.a]) { data.push(vertex1.toList()); - vertex1.sent = true; + this.vertices[currentFace.a] = true; sent++; } - if (!vertex2.sent) { + if (!this.vertices[currentFace.b]) { data.push(vertex2.toList()); - vertex2.sent = true; + this.vertices[currentFace.b] = true; sent++; } - if (!vertex3.sent) { + if (!this.vertices[currentFace.c]) { data.push(vertex3.toList()); - vertex3.sent = true; + this.vertices[currentFace.c] = true; sent++; } - var normal1 = this.normals[currentFace.aNormal]; - var normal2 = this.normals[currentFace.bNormal]; - var normal3 = this.normals[currentFace.cNormal]; + var normal1 = this.mesh.normals[currentFace.aNormal]; + var normal2 = this.mesh.normals[currentFace.bNormal]; + var normal3 = this.mesh.normals[currentFace.cNormal]; - if (normal1 !== undefined && !normal1.sent) { + if (normal1 !== undefined && !this.normals[currentFace.aNormal]) { data.push(normal1.toList()); - normal1.sent = true; + this.normals[currentFace.aNormal] = true; sent++; } - if (normal2 !== undefined && !normal2.sent) { + if (normal2 !== undefined && !this.normals[currentFace.bNormal]) { data.push(normal2.toList()); - normal2.sent = true; + this.normals[currentFace.bNormal] = true; sent++; } - if (normal3 !== undefined && !normal3.sent) { + if (normal3 !== undefined && !this.normals[currentFace.cNormal]) { data.push(normal3.toList()); - normal3.sent = true; + this.normals[currentFace.cNormal] = true; sent++; } - var tex1 = this.texCoords[currentFace.aTexture]; - var tex2 = this.texCoords[currentFace.bTexture]; - var tex3 = this.texCoords[currentFace.cTexture]; + var tex1 = this.mesh.texCoords[currentFace.aTexture]; + var tex2 = this.mesh.texCoords[currentFace.bTexture]; + var tex3 = this.mesh.texCoords[currentFace.cTexture]; - if (tex1 !== undefined && !tex1.sent) { + if (tex1 !== undefined && !this.texCoords[currentFace.aTexture]) { data.push(tex1.toList()); - tex1.sent = true; + this.texCoords[currentFace.aTexture] = true; sent++; } - if (tex2 !== undefined && !tex2.sent) { + if (tex2 !== undefined && !this.texCoords[currentFace.bTexture]) { data.push(tex2.toList()); - tex2.sent = true; + this.texCoords[currentFace.bTexture] = true; sent++; } - if (tex3 !== undefined && !tex3.sent) { + if (tex3 !== undefined && !this.texCoords[currentFace.cTexture]) { data.push(tex3.toList()); - tex3.sent = true; + this.texCoords[currentFace.cTexture] = true; sent++; }