Forráskód Böngészése

Merge pull request #8208 from stity/binaryVTKLoader

Binary VTK parser and support for triangle strip
Mr.doob 9 éve
szülő
commit
8e026aa314
1 módosított fájl, 281 hozzáadás és 7 törlés
  1. 281 7
      examples/js/loaders/VTKLoader.js

+ 281 - 7
examples/js/loaders/VTKLoader.js

@@ -3,7 +3,7 @@
  * @author Alex Pletzer
  */
 
-THREE.VTKLoader = function ( manager ) {
+THREE.VTKLoader = function( manager ) {
 
 	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
 
@@ -13,22 +13,40 @@ THREE.VTKLoader.prototype = {
 
 	constructor: THREE.VTKLoader,
 
-	load: function ( url, onLoad, onProgress, onError ) {
+	load: function( url, onLoad, onProgress, onError ) {
 
 		// Will we bump into trouble reading the whole file into memory?
 		var scope = this;
 		var loader = new THREE.XHRLoader( scope.manager );
-		loader.load( url, function ( text ) {
+		loader.setResponseType( 'arraybuffer' );
+		loader.load( url, function( text ) {
 
 			onLoad( scope.parse( text ) );
 
 		},
 
-		onProgress, onError );
+					onProgress, onError );
 
 	},
 
-	parse: function ( data ) {
+	parse: function( data ) {
+
+		//get the 5 first lines of the files to check if there is the key word binary
+		var meta = String.fromCharCode.apply( null, new Uint8Array( data, 0, 250 ) ).split( '\n' );
+		console.log( meta );
+		if ( meta[ 2 ] === 'ASCII' ) {
+
+			return this.parseASCII( String.fromCharCode.apply( null, new Uint8Array( data ) ) );
+
+		} else {
+
+			return this.parseBinary( data );
+
+		}
+
+	},
+
+	parseASCII: function( data ) {
 
 		// connectivity of the triangles
 		var indices = [];
@@ -57,6 +75,9 @@ THREE.VTKLoader.prototype = {
 		// indicates start of polygon connectivity section
 		var patPOLYGONS = /^POLYGONS /;
 
+		// indicates start of triangle strips section
+		var patTRIANGLE_STRIPS = /^TRIANGLE_STRIPS /;
+
 		// POINT_DATA number_of_values
 		var patPOINT_DATA = /^POINT_DATA[ ]+(\d+)/;
 
@@ -71,6 +92,7 @@ THREE.VTKLoader.prototype = {
 
 		var inPointsSection = false;
 		var inPolygonsSection = false;
+		var inTriangleStripSection = false;
 		var inPointDataSection = false;
 		var inCellDataSection = false;
 		var inColorSection = false;
@@ -111,7 +133,7 @@ THREE.VTKLoader.prototype = {
 						for ( var j = 0; j < numVertices - 2; ++ j ) {
 
 							i1 = parseInt( inds[ k ] );
-							i2 = parseInt( inds[ k  + 1 ] );
+							i2 = parseInt( inds[ k + 1 ] );
 							indices.push( i0, i1, i2 );
 							k ++;
 
@@ -121,6 +143,42 @@ THREE.VTKLoader.prototype = {
 
 				}
 
+			} else if ( inTriangleStripSection ) {
+
+				if ( ( result = patConnectivity.exec( line ) ) !== null ) {
+
+					// numVertices i0 i1 i2 ...
+					var numVertices = parseInt( result[ 1 ] );
+					var inds = result[ 2 ].split( /\s+/ );
+
+					if ( numVertices >= 3 ) {
+
+						var i0, i1, i2;
+						// split the polygon in numVertices - 2 triangles
+						for ( var j = 0; j < numVertices - 2; j ++ ) {
+
+							if ( j % 2 === 1 ) {
+
+								i0 = parseInt( inds[ j ] );
+								i1 = parseInt( inds[ j + 2 ] );
+								i2 = parseInt( inds[ j + 1 ] );
+								indices.push( i0, i1, i2 );
+
+							} else {
+
+								i0 = parseInt( inds[ j ] );
+								i1 = parseInt( inds[ j + 1 ] );
+								i2 = parseInt( inds[ j + 2 ] );
+								indices.push( i0, i1, i2 );
+
+							}
+
+						}
+
+					}
+
+				}
+
 			} else if ( inPointDataSection || inCellDataSection ) {
 
 				if ( inColorSection ) {
@@ -157,23 +215,33 @@ THREE.VTKLoader.prototype = {
 
 				inPolygonsSection = true;
 				inPointsSection = false;
+				inTriangleStripSection = false;
 
 			} else if ( patPOINTS.exec( line ) !== null ) {
 
 				inPolygonsSection = false;
 				inPointsSection = true;
+				inTriangleStripSection = false;
+
+			} else if ( patTRIANGLE_STRIPS.exec( line ) !== null ) {
+
+				inPolygonsSection = false;
+				inPointsSection = false;
+				inTriangleStripSection = true;
 
 			} else if ( patPOINT_DATA.exec( line ) !== null ) {
 
 				inPointDataSection = true;
 				inPointsSection = false;
 				inPolygonsSection = false;
+				inTriangleStripSection = false;
 
 			} else if ( patCELL_DATA.exec( line ) !== null ) {
 
 				inCellDataSection = true;
 				inPointsSection = false;
 				inPolygonsSection = false;
+				inTriangleStripSection = false;
 
 			} else if ( patCOLOR_SCALARS.exec( line ) !== null ) {
 
@@ -181,6 +249,7 @@ THREE.VTKLoader.prototype = {
 				inNormalsSection = false;
 				inPointsSection = false;
 				inPolygonsSection = false;
+				inTriangleStripSection = false;
 
 			} else if ( patNORMALS.exec( line ) !== null ) {
 
@@ -188,6 +257,7 @@ THREE.VTKLoader.prototype = {
 				inColorSection = false;
 				inPointsSection = false;
 				inPolygonsSection = false;
+				inTriangleStripSection = false;
 
 			}
 
@@ -265,10 +335,214 @@ THREE.VTKLoader.prototype = {
 
 				}
 
-			 }
+			}
 
 		}
 
+		return geometry;
+
+	},
+
+	parseBinary: function( data ) {
+
+		var count, pointIndex, i, numberOfPoints, pt, s;
+		var buffer = new Uint8Array ( data );
+		var dataView = new DataView ( data );
+
+		// Points and normals, by default, are empty
+		var points = [];
+		var normals = [];
+		var indices = [];
+
+		// Going to make a big array of strings
+		var vtk = [];
+		var index = 0;
+
+		var findString = function( buffer, start ) {
+
+			var index = start;
+			var c = buffer[ index ];
+			var s = [];
+			while ( c != 10 ) {
+
+				s.push ( String.fromCharCode ( c ) );
+				index ++;
+				c = buffer[ index ];
+
+			}
+
+			return { start: start,
+					end: index,
+					next: index + 1,
+					parsedString: s.join( '' ) };
+
+		}
+
+
+		var state, line;
+
+		while ( true ) {
+
+			// Get a string
+			state = findString ( buffer, index );
+			line = state.parsedString;
+			if ( line.indexOf ( "POINTS" ) == 0 ) {
+
+				vtk.push ( line );
+				// Add the points
+				numberOfPoints = parseInt ( line.split( " " )[ 1 ], 10 );
+
+				// Each point is 3 4-byte floats
+				count = numberOfPoints * 4 * 3;
+
+				points = new Float32Array( numberOfPoints * 3 );
+
+				pointIndex = state.next;
+				for ( i = 0; i < numberOfPoints; i ++ ) {
+
+					points[ 3 * i ] = dataView.getFloat32( pointIndex, false );
+					points[ 3 * i + 1 ] = dataView.getFloat32( pointIndex + 4, false );
+					points[ 3 * i + 2 ] = dataView.getFloat32( pointIndex + 8, false );
+					pointIndex = pointIndex + 12;
+
+				}
+				// increment our next pointer
+				state.next = state.next + count + 1;
+
+			} else if ( line.indexOf ( "TRIANGLE_STRIPS" ) === 0 ) {
+
+				var numberOfStrips = parseInt ( line.split( " " )[ 1 ], 10 );
+				var size = parseInt ( line.split ( " " )[ 2 ], 10 );
+				// 4 byte integers
+				count = size * 4;
+
+				indices = new Uint32Array( 3 * size - 9 * numberOfStrips );
+				var indicesIndex = 0;
+
+				pointIndex = state.next;
+				for ( i = 0; i < numberOfStrips; i ++ ) {
+
+					// For each strip, read the first value, then record that many more points
+					var indexCount = dataView.getInt32( pointIndex, false );
+					var strip = [];
+					pointIndex += 4;
+					for ( s = 0; s < indexCount; s ++ ) {
+
+						strip.push ( dataView.getInt32( pointIndex, false ) );
+						pointIndex += 4;
+
+					}
+
+					// retrieves the n-2 triangles from the triangle strip
+					for ( var j = 0; j < indexCount - 2; j ++ ) {
+
+						if ( j % 2 ) {
+
+							indices[ indicesIndex ++ ] = strip[ j ];
+							indices[ indicesIndex ++ ] = strip[ j + 2 ];
+							indices[ indicesIndex ++ ] = strip[ j + 1 ];
+
+						} else {
+
+
+							indices[ indicesIndex ++ ] = strip[ j ];
+							indices[ indicesIndex ++ ] = strip[ j + 1 ];
+							indices[ indicesIndex ++ ] = strip[ j + 2 ];
+
+						}
+
+					}
+
+				}
+				// increment our next pointer
+				state.next = state.next + count + 1;
+
+			} else if ( line.indexOf ( "POLYGONS" ) === 0 ) {
+
+				var numberOfStrips = parseInt ( line.split( " " )[ 1 ], 10 );
+				var size = parseInt ( line.split ( " " )[ 2 ], 10 );
+				// 4 byte integers
+				count = size * 4;
+
+				indices = new Uint32Array( 3 * size - 9 * numberOfStrips );
+				var indicesIndex = 0;
+
+				pointIndex = state.next;
+				for ( i = 0; i < numberOfStrips; i ++ ) {
+
+					// For each strip, read the first value, then record that many more points
+					var indexCount = dataView.getInt32( pointIndex, false );
+					var strip = [];
+					pointIndex += 4;
+					for ( s = 0; s < indexCount; s ++ ) {
+
+						strip.push ( dataView.getInt32( pointIndex, false ) );
+						pointIndex += 4;
+
+					}
+					var i0 = strip[ 0 ]
+					// divide the polygon in n-2 triangle
+					for ( var j = 1; j < indexCount - 1; j ++ ) {
+
+						indices[ indicesIndex ++ ] = strip[ 0 ];
+						indices[ indicesIndex ++ ] = strip[ j ];
+						indices[ indicesIndex ++ ] = strip[ j + 1 ];
+
+					}
+
+				}
+				// increment our next pointer
+				state.next = state.next + count + 1;
+
+			} else if ( line.indexOf ( "POINT_DATA" ) == 0 ) {
+
+				numberOfPoints = parseInt ( line.split( " " )[ 1 ], 10 );
+
+				// Grab the next line
+				state = findString ( buffer, state.next );
+
+				// Now grab the binary data
+				count = numberOfPoints * 4 * 3;
+
+				normals = new Float32Array( numberOfPoints * 3 );
+				pointIndex = state.next;
+				for ( i = 0; i < numberOfPoints; i ++ ) {
+
+					normals[ 3 * i ] = dataView.getFloat32( pointIndex, false );
+					normals[ 3 * i + 1 ] = dataView.getFloat32( pointIndex + 4, false );
+					normals[ 3 * i + 2 ] = dataView.getFloat32( pointIndex + 8, false );
+					pointIndex += 12;
+
+				}
+
+				// Increment past our data
+				state.next = state.next + count;
+
+			}
+
+			// Increment index
+			index = state.next;
+			if ( index >= buffer.byteLength ) {
+
+				break;
+
+			}
+
+		}
+
+
+		var geometry = new THREE.BufferGeometry();
+		geometry.setIndex( new THREE.BufferAttribute( indices, 1 ) );
+		geometry.addAttribute( 'position', new THREE.BufferAttribute( points, 3 ) );
+
+
+		if ( normals.length == points.length ) {
+
+			geometry.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
+
+		}
+
+
 		return geometry;
 
 	}