From 17bf548feff3220fcc7708da7c4d7c50da879bc1 Mon Sep 17 00:00:00 2001 From: Thomas FORGIONE Date: Tue, 16 Jun 2015 16:35:43 +0200 Subject: [PATCH] Improved performance in streaming --- geo/Mesh.js | 4 +- geo/MeshStreamer.js | 117 ++++++++++++++------------ js/ProgressiveLoader.js | 168 ++++++++++++++++++++------------------ js/prototype/initScene.js | 6 +- js/stream/main.js | 2 +- 5 files changed, 163 insertions(+), 134 deletions(-) diff --git a/geo/Mesh.js b/geo/Mesh.js index f0cf48e..e4174ef 100644 --- a/geo/Mesh.js +++ b/geo/Mesh.js @@ -6,7 +6,7 @@ mesh.Mesh = function() { this.faces = []; this.texCoords = []; this.normals = []; - this.faceIndex = 0; + this.faceIndex = -1; this.material = null; } @@ -79,7 +79,7 @@ mesh.Mesh.prototype.addNormal = function(normal) { } mesh.Mesh.prototype.isFinished = function() { - return this.faces.length === this.faceIndex; + return this.faces.length < this.faceIndex; } // Vertex diff --git a/geo/MeshStreamer.js b/geo/MeshStreamer.js index 9f7436d..423ad89 100644 --- a/geo/MeshStreamer.js +++ b/geo/MeshStreamer.js @@ -117,7 +117,7 @@ geo.MeshStreamer.prototype.loadFromFile = function(path, callback) { geo.MeshStreamer.prototype.start = function(socket) { - this.meshIndex = -1; + this.meshIndex = 0; var self = this; @@ -142,68 +142,85 @@ geo.MeshStreamer.prototype.start = function(socket) { // Send next elements var currentMesh = self.meshes[self.meshIndex]; + var currentFace; - if (currentMesh === undefined || currentMesh.isFinished()) { - currentMesh = self.meshes[++self.meshIndex]; + var data = []; + + var sent = 0; + + while (sent < 500) { + + if (currentMesh.faceIndex === -1) { + + // Must give usemtl + data.push(['u', currentMesh.material, currentMesh.vertices.length, currentMesh.faces.length, self.texCoords.length > 0, self.normals.length > 0]); + sent++; + currentFace = currentMesh.faces[++currentMesh.faceIndex]; + + } else if (currentMesh.isFinished()) { + + // Must switch to next mesh + currentMesh = self.meshes[++self.meshIndex]; + + // If not other mesh, we finished + if (currentMesh === undefined) { + + socket.emit('elements', data); + socket.disconnect(); + return; + + } + + data.push(['u', currentMesh.material, currentMesh.vertices.length, currentMesh.faces.length, self.texCoords.length > 0, self.normals.length > 0]); + sent++; + continue; + + } else { + + currentFace = currentMesh.faces[++currentMesh.faceIndex]; + + if (currentFace === undefined) { + + continue; + + } - if (currentMesh === undefined) { - socket.emit('finished'); - socket.disconnect(); - return; } - socket.emit( - 'usemtl', - currentMesh.material, - currentMesh.vertices.length, - currentMesh.faces.length, - self.texCoords.length > 0, - self.normals.length > 0 - ); + var vertex1 = self.vertices[currentFace.a]; + var vertex2 = self.vertices[currentFace.b]; + var vertex3 = self.vertices[currentFace.c]; - } else { + if (!vertex1.sent) { data.push(vertex1.toList()); vertex1.sent = true; sent++;} + if (!vertex2.sent) { data.push(vertex2.toList()); vertex2.sent = true; sent++;} + if (!vertex3.sent) { data.push(vertex3.toList()); vertex3.sent = true; sent++;} - var data = []; + var normal1 = self.normals[currentFace.aNormal]; + var normal2 = self.normals[currentFace.bNormal]; + var normal3 = self.normals[currentFace.cNormal]; - for (var limit = Math.min(currentMesh.faceIndex + self.chunk, currentMesh.faces.length); - currentMesh.faceIndex < limit; - currentMesh.faceIndex++) - { + if (normal1 !== undefined && !normal1.sent) { data.push(normal1.toList()); normal1.sent = true; sent++;} + if (normal2 !== undefined && !normal2.sent) { data.push(normal2.toList()); normal2.sent = true; sent++;} + if (normal3 !== undefined && !normal3.sent) { data.push(normal3.toList()); normal3.sent = true; sent++;} - var currentFace = currentMesh.faces[currentMesh.faceIndex]; - var vertex1 = self.vertices[currentFace.a]; - var vertex2 = self.vertices[currentFace.b]; - var vertex3 = self.vertices[currentFace.c]; + var tex1 = self.texCoords[currentFace.aTexture]; + var tex2 = self.texCoords[currentFace.bTexture]; + var tex3 = self.texCoords[currentFace.cTexture]; - if (!vertex1.sent) { data.push(vertex1.toList()); vertex1.sent = true;} - if (!vertex2.sent) { data.push(vertex2.toList()); vertex2.sent = true;} - if (!vertex3.sent) { data.push(vertex3.toList()); vertex3.sent = true;} + if (tex1 !== undefined && !tex1.sent) { data.push(tex1.toList()); tex1.sent = true; sent++;} + if (tex2 !== undefined && !tex2.sent) { data.push(tex2.toList()); tex2.sent = true; sent++;} + if (tex3 !== undefined && !tex3.sent) { data.push(tex3.toList()); tex3.sent = true; sent++;} - var normal1 = self.normals[currentFace.aNormal]; - var normal2 = self.normals[currentFace.bNormal]; - var normal3 = self.normals[currentFace.cNormal]; + currentFace.index = currentMesh.faceIndex; - if (normal1 !== undefined && !normal1.sent) { data.push(normal1.toList()); normal1.sent = true;} - if (normal2 !== undefined && !normal2.sent) { data.push(normal2.toList()); normal2.sent = true;} - if (normal3 !== undefined && !normal3.sent) { data.push(normal3.toList()); normal3.sent = true;} - - var tex1 = self.texCoords[currentFace.aTexture]; - var tex2 = self.texCoords[currentFace.bTexture]; - var tex3 = self.texCoords[currentFace.cTexture]; - - if (tex1 !== undefined && !tex1.sent) { data.push(tex1.toList()); tex1.sent = true;} - if (tex2 !== undefined && !tex2.sent) { data.push(tex2.toList()); tex2.sent = true;} - if (tex3 !== undefined && !tex3.sent) { data.push(tex3.toList()); tex3.sent = true;} - - currentFace.index = currentMesh.faceIndex; - - data.push(currentFace.toList()); currentFace.sent = true; - } - - // Emit self.chunk faces (and the corresponding vertices if not emitted) - socket.emit('elements', data); + data.push(currentFace.toList()); currentFace.sent = true; + sent++; } + + // Emit self.chunk faces (and the corresponding vertices if not emitted) + socket.emit('elements', data); + }); } diff --git a/js/ProgressiveLoader.js b/js/ProgressiveLoader.js index ffec714..7ba34af 100644 --- a/js/ProgressiveLoader.js +++ b/js/ProgressiveLoader.js @@ -47,6 +47,17 @@ var _parseList = function(arr) { ret.y = arr[3]; ret.z = arr[4]; + } else if (arr[0] === 'u') { + + // usemtl + ret.index = -1; + ret.type = 'usemtl'; + ret.materialName = arr[1]; + ret.vLength = arr[2]; + ret.fLength = arr[3]; + ret.texCoordsExist = arr[4]; + ret.normalsExist = arr[5]; + } return ret; @@ -97,84 +108,6 @@ ProgressiveLoader.prototype.initIOCallbacks = function() { var self = this; - this.socket.on('usemtl', function(materialName, verticesNumber, facesNumber, texCoordsExist, normalsExist) { - - // console.log("New mesh arrived : " + materialName); - if (self.currentMesh !== undefined && self.currentMesh.visible === false) { - self.currentMesh.geometry.computeBoundingSphere(); - - if (self.currentMesh.geometry.attributes.normal === undefined) { - self.currentMesh.geometry.computeVertexNormals(); - } - - self.currentMesh.visible = true; - } - - // Create mesh material - var material; - - if (materialName === null) { - - // If no material, create a default material - material = new THREE.MeshLambertMaterial({color: 'red'}); - - } else { - - // If material name exists, load if from material, and do a couple of settings - material = self.materialCreator.materials[materialName.trim()]; - - material.side = THREE.DoubleSide; - - if (material.map) - material.map.wrapS = material.map.wrapT = THREE.RepeatWrapping; - } - - // Create mesh geometry - var geometry = new THREE.BufferGeometry(); - geometry.dynamic = true; - - var positionArray = new Float32Array(facesNumber * 3 * 3); - var positionAttribute = new THREE.BufferAttribute(positionArray, 3); - - geometry.addAttribute('position', positionAttribute); - - // Add other attributes if necessary - if (texCoordsExist) { - - // console.log("Mesh with textures"); - - var uvArray = new Float32Array(facesNumber * 3 * 2); - var uvAttribute = new THREE.BufferAttribute(uvArray, 2); - - geometry.addAttribute('uv', uvAttribute); - } - - if (normalsExist) { - - // console.log("Mesh with normals"); - - var normalArray = new Float32Array(facesNumber * 3 * 3); - var normalAttribute = new THREE.BufferAttribute(normalArray, 3); - - geometry.addAttribute('normal', normalAttribute); - - } - - // Create mesh - var mesh = new THREE.Mesh(geometry, material); - - self.currentMesh = mesh; - self.obj.add(mesh); - mesh.visible = false; - - if (typeof self.callback === 'function') { - self.callback(mesh); - } - - // Ask for next - self.socket.emit('next'); - }); - this.socket.on('ok', function() { console.log('ok'); self.socket.emit('next'); @@ -183,7 +116,6 @@ ProgressiveLoader.prototype.initIOCallbacks = function() { this.socket.on('elements', function(arr) { // console.log("Received elements for the " + (++self.counter) + "th time !"); - for (var i = 0; i < arr.length; i++) { var elt = _parseList(arr[i]); @@ -204,6 +136,83 @@ ProgressiveLoader.prototype.initIOCallbacks = function() { // New normal arrived self.normals[elt.index] = [elt.x, elt.y, elt.z]; + } else if (elt.type === 'usemtl') { + + if (self.currentMesh !== undefined) { + + self.currentMesh.geometry.computeBoundingSphere(); + + if (self.currentMesh.geometry.attributes.normal === undefined) { + + self.currentMesh.geometry.computeVertexNormals(); + + } + + } + + // Must create new mesh + // console.log("New mesh arrived : " + elt.materialName); + + // Create mesh material + var material; + + if (elt.materialName === null) { + + // If no material, create a default material + material = new THREE.MeshLambertMaterial({color: 'red'}); + + } else { + + // If material name exists, load if from material, and do a couple of settings + material = self.materialCreator.materials[elt.materialName.trim()]; + + material.side = THREE.DoubleSide; + + if (material.map) + material.map.wrapS = material.map.wrapT = THREE.RepeatWrapping; + } + + // Create mesh geometry + var geometry = new THREE.BufferGeometry(); + geometry.dynamic = true; + + var positionArray = new Float32Array(elt.fLength * 3 * 3); + var positionAttribute = new THREE.BufferAttribute(positionArray, 3); + + geometry.addAttribute('position', positionAttribute); + + // Add other attributes if necessary + if (elt.texCoordsExist) { + + // console.log("Mesh with textures"); + + var uvArray = new Float32Array(elt.fLength * 3 * 2); + var uvAttribute = new THREE.BufferAttribute(uvArray, 2); + + geometry.addAttribute('uv', uvAttribute); + } + + if (elt.normalsExist) { + + // console.log("Mesh with normals"); + + var normalArray = new Float32Array(elt.fLength * 3 * 3); + var normalAttribute = new THREE.BufferAttribute(normalArray, 3); + + geometry.addAttribute('normal', normalAttribute); + + } + + // Create mesh + var mesh = new THREE.Mesh(geometry, material); + + self.currentMesh = mesh; + self.obj.add(mesh); + + if (typeof self.callback === 'function') { + self.callback(mesh); + } + } else if (elt.type === 'face') { // New face arrived : add it into current mesh @@ -269,7 +278,6 @@ ProgressiveLoader.prototype.initIOCallbacks = function() { if (self.currentMesh.geometry.attributes.normal === undefined) { self.currentMesh.geometry.computeVertexNormals(); } - self.currentMesh.visible = true; self.finished = true; }); } diff --git a/js/prototype/initScene.js b/js/prototype/initScene.js index 863863b..34ad914 100644 --- a/js/prototype/initScene.js +++ b/js/prototype/initScene.js @@ -616,12 +616,16 @@ function initSponzaScene(scene, collidableObjects, loader, static_path) { } + obj.raycastable = true; + }); loader.load(); - glob = loader.obj; loader.obj.scale.set(0.1,0.1,0.1); + collidableObjects.push(loader.obj); + loader.obj.raycastable = true; + // ProgressiveLoader('/static/data/sponza/sponza.obj', scene, // function(obj) { // obj.scale.set(0.1,0.1,0.1); diff --git a/js/stream/main.js b/js/stream/main.js index a72ad07..ae69e2b 100644 --- a/js/stream/main.js +++ b/js/stream/main.js @@ -45,7 +45,7 @@ function init() { // Load the scene // loader = new THREE.OBJLoader(); - sphereLoader = new ProgressiveLoader('static/data/spheres/' + params.get.res + '.obj', scene); + sphereLoader = new ProgressiveLoader('/static/data/spheres/' + params.get.res + '.obj', scene); sphereLoader.load(); sphere = sphereLoader.obj;