Преглед на файлове

CTMLoader can now properly load very large models by using now uses BufferGeometry's computeOffsets.

This ensures that all the index buffer uses only 16-bit addressable vertices per draw offset. The previous chunking algorithm referenced in the loader would create a huge amount of draw calls when large meshes would reuse many vertices.
Ref: #3524
Benoit Beausejour преди 11 години
родител
ревизия
8b74317c49
променени са 1 файла, в които са добавени 14 реда и са изтрити 213 реда
  1. 14 213
      examples/js/loaders/ctm/CTMLoader.js

+ 14 - 213
examples/js/loaders/ctm/CTMLoader.js

@@ -78,7 +78,7 @@ THREE.CTMLoader.prototype.loadParts = function( url, callback, parameters ) {
 };
 };
 
 
 // Load CTMLoader compressed models
 // Load CTMLoader compressed models
-//  - parameters
+//	- parameters
 //		- url (required)
 //		- url (required)
 //		- callback (required)
 //		- callback (required)
 
 
@@ -116,8 +116,8 @@ THREE.CTMLoader.prototype.load = function( url, callback, parameters ) {
 
 
 							var ctmFile = files[ i ];
 							var ctmFile = files[ i ];
 
 
-                            				var e1 = Date.now();
-                            				// console.log( "CTM data parse time [worker]: " + (e1-s) + " ms" );
+																		var e1 = Date.now();
+																		// console.log( "CTM data parse time [worker]: " + (e1-s) + " ms" );
 
 
 							if ( useBuffers ) {
 							if ( useBuffers ) {
 
 
@@ -129,8 +129,8 @@ 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( "model load time [worker]: " + (e-e1) + " ms, total: " + (e-s));
 
 
 						}
 						}
 
 
@@ -207,15 +207,11 @@ THREE.CTMLoader.prototype.createModelBuffers = function ( file, callback ) {
 
 
 		var scope = this;
 		var scope = this;
 
 
-		var reorderVertices = true;
-
 		scope.materials = [];
 		scope.materials = [];
 
 
 		THREE.BufferGeometry.call( this );
 		THREE.BufferGeometry.call( this );
 
 
-		var s = Date.now();
 		// init GL buffers
 		// init GL buffers
-
 		var vertexIndexArray = file.body.indices,
 		var vertexIndexArray = file.body.indices,
 		vertexPositionArray = file.body.vertices,
 		vertexPositionArray = file.body.vertices,
 		vertexNormalArray = file.body.normals;
 		vertexNormalArray = file.body.normals;
@@ -230,226 +226,31 @@ THREE.CTMLoader.prototype.createModelBuffers = function ( file, callback ) {
 			vertexColorArray = file.body.attrMaps[ 0 ].attr;
 			vertexColorArray = file.body.attrMaps[ 0 ].attr;
 		}
 		}
 
 
-		// reorder vertices
-		// (needed for buffer splitting, to keep together face vertices)
-		if ( reorderVertices ) {
-
-		    	function copyVertexInfo(v, vt) {
-
-				var sx = v * 3,
-			    	    sy = v * 3 + 1,
-			    	    sz = v * 3 + 2,
-
-			    	dx = vt * 3,
-			    	dy = vt * 3 + 1,
-			    	dz = vt * 3 + 2;
-
-				newVertices[ dx ] = vertexPositionArray[ sx ];
-				newVertices[ dy ] = vertexPositionArray[ sy ];
-				newVertices[ dz ] = vertexPositionArray[ sz ];
-
-				if ( vertexNormalArray ) {
-				    newNormals[ dx ] = vertexNormalArray[ sx ];
-				    newNormals[ dy ] = vertexNormalArray[ sy ];
-				    newNormals[ dz ] = vertexNormalArray[ sz ];
-				}
-
-				if ( vertexUvArray ) {
-				    newUvs[ vt * 2 ] 	 = vertexUvArray[ v * 2 ];
-				    newUvs[ vt * 2 + 1 ] = vertexUvArray[ v * 2 + 1 ];
-				}
-
-				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 ];
-				}
-		    	}
-
-		    	function handleVertex( v, iMap ) {
-
-				if ( iMap[ v ] === undefined ) {
-
-					iMap[ v ] = vertexCounter;
-                    			reverseIndexMap[vertexCounter] = v;
-					vertexCounter += 1;
-				}
-                		return iMap[ v ];
-		    	}
-
-			var newFaces = new Uint32Array( vertexIndexArray.length );
-			var indexMap = {}, reverseIndexMap = {}, vertexCounter = 0;
-
-            		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);
-
-			// create dublicate vertices and update sprawled faces
-			var indexMap2 = {},
-			    noov = vertexCounter;   // # of original vertices
-
-			for (var isf = 0; isf < spawledFaceCount; isf++ ) {
-				var i = sprawledFaces[isf];
-
-				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));
-
-			// copy xyz, uv, normals and colors into new arrays
-			var newVertices = new Float32Array( 3*vertexCounter );
-			var newNormals, newUvs, newColors;
-
-			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;
-
-			if ( vertexNormalArray ) vertexNormalArray = newNormals;
-			if ( vertexUvArray ) vertexUvArray = newUvs;
-			if ( vertexColorArray ) vertexColorArray = newColors;
-		}
-
-		// compute offsets
-
-		scope.offsets = [];
-
-		var indices = vertexIndexArray;
-
-		var start = 0,
-			min = vertexPositionArray.length,
-			max = 0,
-			minPrev = min;
-
-		for ( var i = 0; i < indices.length; ) {
-
-			for ( var j = 0; j < 3; ++ j ) {
-
-				var idx = indices[ i ++ ];
-
-				if ( idx < min ) min = idx;
-				if ( idx > max ) max = idx;
-
-			}
-
-			if ( max - min > 65535 ) {
-
-				i -= 3;
-
-                		if ( minPrev > 0 ) {
-
-				    for ( var k = start; k < i; ++ k )
-					    indices[ k ] -= minPrev;
-				}
-
-				scope.offsets.push( { start: start, count: i - start, index: minPrev } );
-
-				start = i;
-				min = vertexPositionArray.length;
-				max = 0;
-
-			}
-
-			minPrev = min;
-
-		}
-
-        	if ( minPrev > 0 ) {
-
-		    for ( var k = start; k < i; ++ k )
-			    indices[ k ] -= minPrev;
-		}
-		scope.offsets.push( { start: start, count: i - start, index: minPrev } );
-
-        	// 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
 		// attributes
 		var attributes = scope.attributes;
 		var attributes = scope.attributes;
 
 
-		attributes[ "index" ]    = { itemSize: 1, array: vertexIndexArray16 };
+		attributes[ "index" ]		 = { itemSize: 1, array: vertexIndexArray };
 		attributes[ "position" ] = { itemSize: 3, array: vertexPositionArray };
 		attributes[ "position" ] = { itemSize: 3, array: vertexPositionArray };
 
 
-		if ( vertexNormalArray !== undefined ) {
-
+		if ( vertexNormalArray !== undefined ) 
 			attributes[ "normal" ] = { itemSize: 3, array: vertexNormalArray };
 			attributes[ "normal" ] = { itemSize: 3, array: vertexNormalArray };
 
 
-		}
-
-		if ( vertexUvArray !== undefined ) {
-
+		if ( vertexUvArray !== undefined ) 
 			attributes[ "uv" ] = { itemSize: 2, array: vertexUvArray };
 			attributes[ "uv" ] = { itemSize: 2, array: vertexUvArray };
 
 
-		}
-
-		if ( vertexColorArray !== undefined ) {
-
+		if ( vertexColorArray !== undefined ) 
 			attributes[ "color" ]  = { itemSize: 4, array: vertexColorArray };
 			attributes[ "color" ]  = { itemSize: 4, array: vertexColorArray };
-
-		}
-
 	}
 	}
 
 
 	Model.prototype = Object.create( THREE.BufferGeometry.prototype );
 	Model.prototype = Object.create( THREE.BufferGeometry.prototype );
 
 
 	var geometry = new Model();
 	var geometry = new Model();
 
 
-	// compute vertex normals if not present in the CTM model
+	geometry.computeOffsets();
 
 
+	// compute vertex normals if not present in the CTM model
 	if ( geometry.attributes[ "normal" ] === undefined ) {
 	if ( geometry.attributes[ "normal" ] === undefined ) {
-
 		geometry.computeVertexNormals();
 		geometry.computeVertexNormals();
-
 	}
 	}
 
 
 	callback( geometry );
 	callback( geometry );
@@ -631,15 +432,15 @@ THREE.CTMLoader.prototype.createModelClassic = function ( file, callback ) {
 
 
 	function f3n ( scope, normals, a, b, c, mi, nai, nbi, nci ) {
 	function f3n ( scope, normals, a, b, c, mi, nai, nbi, nci ) {
 
 
-		var nax = normals[ nai * 3     ],
+		var nax = normals[ nai * 3		 ],
 			nay = normals[ nai * 3 + 1 ],
 			nay = normals[ nai * 3 + 1 ],
 			naz = normals[ nai * 3 + 2 ],
 			naz = normals[ nai * 3 + 2 ],
 
 
-			nbx = normals[ nbi * 3     ],
+			nbx = normals[ nbi * 3		 ],
 			nby = normals[ nbi * 3 + 1 ],
 			nby = normals[ nbi * 3 + 1 ],
 			nbz = normals[ nbi * 3 + 2 ],
 			nbz = normals[ nbi * 3 + 2 ],
 
 
-			ncx = normals[ nci * 3     ],
+			ncx = normals[ nci * 3		 ],
 			ncy = normals[ nci * 3 + 1 ],
 			ncy = normals[ nci * 3 + 1 ],
 			ncz = normals[ nci * 3 + 2 ];
 			ncz = normals[ nci * 3 + 2 ];