diff --git a/examples/js/loaders/VTKLoader.js b/examples/js/loaders/VTKLoader.js index 7d1f9b4fef33b591b73818fdce01390571f28132..8714f93fb1561099ca0ea7f1d70139298202d112 100644 --- a/examples/js/loaders/VTKLoader.js +++ b/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; }