Browse Source

fixes for sprawled faces for BufferGeometry

Updated vertices reordering to deal with sprawled faces in large models
(for BufferGeometry)
Simon 12 years ago
parent
commit
ebbf99a78a
1 changed files with 111 additions and 74 deletions
  1. 111 74
      examples/js/loaders/ctm/CTMLoader.js

+ 111 - 74
examples/js/loaders/ctm/CTMLoader.js

@@ -103,7 +103,7 @@ THREE.CTMLoader.prototype.load = function( url, callback, parameters ) {
 
 				var binaryData = xhr.responseText;
 
-				//var s = Date.now();
+				var s = Date.now();
 
 				if ( parameters.useWorker ) {
 
@@ -117,6 +117,9 @@ THREE.CTMLoader.prototype.load = function( url, callback, parameters ) {
 
 							var ctmFile = files[ i ];
 
+                            var e1 = Date.now();
+                            // console.log( "CTM data parse time [worker]: " + (e1-s) + " ms" );
+
 							if ( useBuffers ) {
 
 								scope.createModelBuffers( ctmFile, callback );
@@ -127,10 +130,11 @@ THREE.CTMLoader.prototype.load = function( url, callback, parameters ) {
 
 							}
 
+                            var e = Date.now();
+                            console.log( "model load time [worker]: " + (e-e1) + " ms, total: " + (e-s));
+
 						}
 
-						//var e = Date.now();
-						//console.log( "CTM data parse time [worker]: " + (e-s) + " ms" );
 
 					};
 
@@ -209,6 +213,7 @@ THREE.CTMLoader.prototype.createModelBuffers = function ( file, callback ) {
 
 		THREE.BufferGeometry.call( this );
 
+		var s = Date.now();
 		// init GL buffers
 
 		var vertexIndexArray = file.body.indices,
@@ -218,98 +223,131 @@ THREE.CTMLoader.prototype.createModelBuffers = function ( file, callback ) {
 		var vertexUvArray, vertexColorArray;
 
 		if ( file.body.uvMaps !== undefined && file.body.uvMaps.length > 0 ) {
-
 			vertexUvArray = file.body.uvMaps[ 0 ].uv;
-
 		}
 
 		if ( file.body.attrMaps !== undefined && file.body.attrMaps.length > 0 && file.body.attrMaps[ 0 ].name === "Color" ) {
-
 			vertexColorArray = file.body.attrMaps[ 0 ].attr;
-
 		}
 
 		// reorder vertices
 		// (needed for buffer splitting, to keep together face vertices)
-
 		if ( reorderVertices ) {
 
-			var newFaces = new Uint32Array( vertexIndexArray.length ),
-				newVertices = new Float32Array( vertexPositionArray.length );
-
-			var newNormals, newUvs, newColors;
-
-			if ( vertexNormalArray ) newNormals = new Float32Array( vertexNormalArray.length );
-			if ( vertexUvArray ) newUvs = new Float32Array( vertexUvArray.length );
-			if ( vertexColorArray ) newColors = new Float32Array( vertexColorArray.length );
-
-			var indexMap = {}, vertexCounter = 0;
-
-			function handleVertex( v ) {
+            function copyVertexInfo(v, vt) {
 
-				if ( indexMap[ v ] === undefined ) {
+                var sx = v * 3,
+                    sy = v * 3 + 1,
+                    sz = v * 3 + 2,
 
-					indexMap[ v ] = vertexCounter;
+                    dx = vt * 3,
+                    dy = vt * 3 + 1,
+                    dz = vt * 3 + 2;
 
-					var sx = v * 3,
-						sy = v * 3 + 1,
-						sz = v * 3 + 2,
+                newVertices[ dx ] = vertexPositionArray[ sx ];
+                newVertices[ dy ] = vertexPositionArray[ sy ];
+                newVertices[ dz ] = vertexPositionArray[ sz ];
 
-						dx = vertexCounter * 3,
-						dy = vertexCounter * 3 + 1,
-						dz = vertexCounter * 3 + 2;
+                if ( vertexNormalArray ) {
+                    newNormals[ dx ] = vertexNormalArray[ sx ];
+                    newNormals[ dy ] = vertexNormalArray[ sy ];
+                    newNormals[ dz ] = vertexNormalArray[ sz ];
+                }
 
-					newVertices[ dx ] = vertexPositionArray[ sx ];
-					newVertices[ dy ] = vertexPositionArray[ sy ];
-					newVertices[ dz ] = vertexPositionArray[ sz ];
+                if ( vertexUvArray ) {
+                    newUvs[ vt * 2 ] 	 = vertexUvArray[ v * 2 ];
+                    newUvs[ vt * 2 + 1 ] = vertexUvArray[ v * 2 + 1 ];
+                }
 
-					if ( vertexNormalArray ) {
+                if ( vertexColorArray ) {
+                    newColors[ vt * 4 ] 	= vertexColorArray[ v * 4 ];
+                    newColors[ vt * 4 + 1 ] = vertexColorArray[ v * 4 + 1 ];
+                    newColors[ vt * 4 + 2 ] = vertexColorArray[ v * 4 + 2 ];
+                    newColors[ vt * 4 + 3 ] = vertexColorArray[ v * 4 + 3 ];
+                }
+            }
 
-						newNormals[ dx ] = vertexNormalArray[ sx ];
-						newNormals[ dy ] = vertexNormalArray[ sy ];
-						newNormals[ dz ] = vertexNormalArray[ sz ];
-
-					}
-
-					if ( vertexUvArray ) {
-
-						newUvs[ vertexCounter * 2 ] 	= vertexUvArray[ v * 2 ];
-						newUvs[ vertexCounter * 2 + 1 ] = vertexUvArray[ v * 2 + 1 ];
-
-					}
+			function handleVertex( v, iMap ) {
 
-					if ( vertexColorArray ) {
+				if ( iMap[ v ] === undefined ) {
 
-						newColors[ vertexCounter * 4 ] 	   = vertexColorArray[ v * 4 ];
-						newColors[ vertexCounter * 4 + 1 ] = vertexColorArray[ v * 4 + 1 ];
-						newColors[ vertexCounter * 4 + 2 ] = vertexColorArray[ v * 4 + 2 ];
-						newColors[ vertexCounter * 4 + 3 ] = vertexColorArray[ v * 4 + 3 ];
+					iMap[ v ] = vertexCounter;
+                    reverseIndexMap[vertexCounter] = v;
+					vertexCounter += 1;
+				}
+                return iMap[ v ];
+			}
 
-					}
+			var newFaces = new Uint32Array( vertexIndexArray.length );
+			var indexMap = {}, reverseIndexMap = {}, vertexCounter = 0;
 
-					vertexCounter += 1;
+            // in most Reality Capture models < 1% of faces**2 are sprawled, for complex CAD/CAM > 2%
+            var spawledFaceCount = 0,
+                spawledFaceLimit = Math.ceil(vertexIndexArray.length/3000);
+            var sprawledFaces = new Uint32Array( spawledFaceLimit );  // to store sprawled triangle indices
 
-				}
+			for ( var i = 0; i < vertexIndexArray.length; i += 3 ) {
 
+				var a = vertexIndexArray[ i ];
+				var b = vertexIndexArray[ i + 1 ];
+				var c = vertexIndexArray[ i + 2 ];
+
+				handleVertex( a, indexMap );
+				handleVertex( b, indexMap );
+				handleVertex( c, indexMap );
+
+				// check for sprawled triangles and put them aside to recreate later
+				if ( Math.abs( indexMap[a] - indexMap[b] ) > 65535 ||
+                     Math.abs( indexMap[b] - indexMap[c] ) > 65535 ||
+                     Math.abs( indexMap[c] - indexMap[a] ) > 65535 ){
+
+                    // expand storage when neccessary
+                    if (spawledFaceCount >= spawledFaceLimit) {
+                        console.warn("reached sprawled faces limit: " + spawledFaceCount);
+                        spawledFaceLimit *= 2;
+                        var tArr = new Uint32Array( spawledFaceLimit );
+                        tArr.set(sprawledFaces);
+                        sprawledFaces = tArr;
+                    }
+
+                    sprawledFaces[ spawledFaceCount ] = i;  // starting index in newFaces
+                    spawledFaceCount += 1;
+                }
+                else {
+
+				    newFaces[ i ] 	  = indexMap[ a ];
+				    newFaces[ i + 1 ] = indexMap[ b ];
+				    newFaces[ i + 2 ] = indexMap[ c ];
+                }
 			}
+            console.log("Number of sprawled faces: " + spawledFaceCount + " current limit: " + spawledFaceLimit +
+                        " total: " + vertexIndexArray.length/3 + " vertices: " + vertexCounter);
 
-			var a, b, c;
+            // create dublicate vertices and update sprawled faces
+            var indexMap2 = {},
+                noov = vertexCounter;   // # of original vertices
 
-			for ( var i = 0; i < vertexIndexArray.length; i += 3 ) {
+            for (var isf = 0; isf < spawledFaceCount; isf++ ) {
+                var i = sprawledFaces[isf];
 
-				a = vertexIndexArray[ i ];
-				b = vertexIndexArray[ i + 1 ];
-				c = vertexIndexArray[ i + 2 ];
+                for (var j = 0; j < 3; j++) {
+                    var v = vertexIndexArray[ i + j ];
+                    newFaces[ i + j] = handleVertex(v, indexMap2);   // new vertex
+                }
+            }
+            // console.log("Created duplicated vertices: " + (vertexCounter - noov));
 
-				handleVertex( a );
-				handleVertex( b );
-				handleVertex( c );
+            // copy xyz, uv, normals and colors into new arrays
+            var newVertices = new Float32Array( 3*vertexCounter );
+			var newNormals, newUvs, newColors;
 
-				newFaces[ i ] 	  = indexMap[ a ];
-				newFaces[ i + 1 ] = indexMap[ b ];
-				newFaces[ i + 2 ] = indexMap[ c ];
+			if ( vertexNormalArray ) newNormals = new Float32Array( 3*vertexCounter );
+			if ( vertexUvArray ) newUvs = new Float32Array( 2*vertexCounter );
+			if ( vertexColorArray ) newColors = new Float32Array( 4*vertexCounter );
 
-			}
+            for (var iv = 0; iv < vertexCounter; iv++) {
+                copyVertexInfo(reverseIndexMap[iv], iv);
+            }
 
 			vertexIndexArray = newFaces;
 			vertexPositionArray = newVertices;
@@ -317,7 +355,6 @@ THREE.CTMLoader.prototype.createModelBuffers = function ( file, callback ) {
 			if ( vertexNormalArray ) vertexNormalArray = newNormals;
 			if ( vertexUvArray ) vertexUvArray = newUvs;
 			if ( vertexColorArray ) vertexColorArray = newColors;
-
 		}
 
 		// compute offsets
@@ -346,10 +383,10 @@ THREE.CTMLoader.prototype.createModelBuffers = function ( file, callback ) {
 
 				i -= 3;
 
-				for ( var k = start; k < i; ++ k ) {
-
-					indices[ k ] -= minPrev;
+                if ( minPrev > 0 ) {
 
+				    for ( var k = start; k < i; ++ k )
+					    indices[ k ] -= minPrev;
 				}
 
 				scope.offsets.push( { start: start, count: i - start, index: minPrev } );
@@ -364,20 +401,20 @@ THREE.CTMLoader.prototype.createModelBuffers = function ( file, callback ) {
 
 		}
 
-		for ( var k = start; k < i; ++ k ) {
-
-			indices[ k ] -= minPrev;
+        if ( minPrev > 0 ) {
 
+		    for ( var k = start; k < i; ++ k )
+			    indices[ k ] -= minPrev;
 		}
-
 		scope.offsets.push( { start: start, count: i - start, index: minPrev } );
 
-		// recast CTM 32-bit indices as 16-bit WebGL indices
+        var e = Date.now();
+		console.log( "Vetex reordering time: " + (e-s) + " ms" );
 
+		// recast CTM 32-bit indices as 16-bit WebGL indices
 		var vertexIndexArray16 = new Uint16Array( vertexIndexArray );
 
 		// attributes
-
 		var attributes = scope.attributes;
 
 		attributes[ "index" ]    = { itemSize: 1, array: vertexIndexArray16, numItems: vertexIndexArray16.length };