diff --git a/examples/files.js b/examples/files.js index 562f7f7f1a60baccd65c778e7c727d044609f9bb..f6f2e6ab611b50c172c997f6fff8d6a8ac1b3891 100644 --- a/examples/files.js +++ b/examples/files.js @@ -111,6 +111,7 @@ var files = { "webgl_loader_pcd", "webgl_loader_pdb", "webgl_loader_ply", + "webgl_loader_prwm", "webgl_loader_ttf", "webgl_loader_sea3d", "webgl_loader_sea3d_hierarchy", diff --git a/examples/js/loaders/PRWMLoader.js b/examples/js/loaders/PRWMLoader.js new file mode 100644 index 0000000000000000000000000000000000000000..108c2e8eff597fd748ad9c4d76008f558617662f --- /dev/null +++ b/examples/js/loaders/PRWMLoader.js @@ -0,0 +1,293 @@ +/** + * @author Kevin Chapelier / https://github.com/kchapelier + * See https://github.com/kchapelier/PRWM for more informations about this file format + */ + +( function ( THREE ) { + + "use strict"; + + var bigEndianPlatform = null; + + /** + * Check if the endianness of the platform is big-endian (most significant bit first) + * @returns {boolean} True if big-endian, false if little-endian + */ + function isBigEndianPlatform() { + + if ( bigEndianPlatform === null ) { + + var buffer = new ArrayBuffer( 2 ), + uint8Array = new Uint8Array( buffer ), + uint16Array = new Uint16Array( buffer ); + + uint8Array[ 0 ] = 0xAA; // set first byte + uint8Array[ 1 ] = 0xBB; // set second byte + bigEndianPlatform = ( uint16Array[ 0 ] === 0xAABB ); + + } + + return bigEndianPlatform; + + } + + // match the values defined in the spec to the TypedArray types + var InvertedEncodingTypes = [ + null, + Float32Array, + null, + Int8Array, + Int16Array, + null, + Int32Array, + Uint8Array, + Uint16Array, + null, + Uint32Array + ]; + + // define the method to use on a DataView, corresponding the TypedArray type + var getMethods = { + Uint16Array: 'getUint16', + Uint32Array: 'getUint32', + Int16Array: 'getInt16', + Int32Array: 'getInt32', + Float32Array: 'getFloat32', + Float64Array: 'getFloat64' + }; + + + function copyFromBuffer( sourceArrayBuffer, viewType, position, length, fromBigEndian ) { + + var bytesPerElement = viewType.BYTES_PER_ELEMENT, + result; + + if ( fromBigEndian === isBigEndianPlatform() || bytesPerElement === 1 ) { + + result = new viewType( sourceArrayBuffer, position, length ); + + } else { + + var readView = new DataView( sourceArrayBuffer, position, length * bytesPerElement ), + getMethod = getMethods[ viewType.name ], + littleEndian = ! fromBigEndian, + i = 0; + + result = new viewType( length ); + + for ( ; i < length; i ++ ) { + + result[ i ] = readView[ getMethod ]( i * bytesPerElement, littleEndian ); + + } + + } + + return result; + + } + + + function decodePrwm( buffer ) { + + var array = new Uint8Array( buffer ), + version = array[ 0 ], + flags = array[ 1 ], + indexedGeometry = !! ( flags >> 7 & 0x01 ), + indicesType = flags >> 6 & 0x01, + bigEndian = ( flags >> 5 & 0x01 ) === 1, + attributesNumber = flags & 0x1F, + valuesNumber = 0, + indicesNumber = 0; + + if ( bigEndian ) { + + valuesNumber = ( array[ 2 ] << 16 ) + ( array[ 3 ] << 8 ) + array[ 4 ]; + indicesNumber = ( array[ 5 ] << 16 ) + ( array[ 6 ] << 8 ) + array[ 7 ]; + + } else { + + valuesNumber = array[ 2 ] + ( array[ 3 ] << 8 ) + ( array[ 4 ] << 16 ); + indicesNumber = array[ 5 ] + ( array[ 6 ] << 8 ) + ( array[ 7 ] << 16 ); + + } + + /** PRELIMINARY CHECKS **/ + + if ( version === 0 ) { + + throw new Error( 'PRWM decoder: Invalid format version: 0' ); + + } else if ( version !== 1 ) { + + throw new Error( 'PRWM decoder: Unsupported format version: ' + version ); + + } + + if ( ! indexedGeometry ) { + + if ( indicesType !== 0 ) { + + throw new Error( 'PRWM decoder: Indices type must be set to 0 for non-indexed geometries' ); + + } else if ( indicesNumber !== 0 ) { + + throw new Error( 'PRWM decoder: Number of indices must be set to 0 for non-indexed geometries' ); + + } + + } + + /** PARSING **/ + + var pos = 8; + + var attributes = {}, + attributeName, + char, + attributeType, + attributeNormalized, + cardinality, + encodingType, + arrayType, + values, + indices, + i; + + for ( i = 0; i < attributesNumber; i ++ ) { + + attributeName = ''; + + while ( pos < array.length ) { + + char = array[ pos ]; + pos ++; + + if ( char === 0 ) { + + break; + + } else { + + attributeName += String.fromCharCode( char ); + + } + + } + + flags = array[ pos ]; + + attributeType = flags >> 7 & 0x01; + attributeNormalized = !! ( flags >> 6 & 0x01 ); + cardinality = ( flags >> 4 & 0x03 ) + 1; + encodingType = flags & 0x0F; + arrayType = InvertedEncodingTypes[ encodingType ]; + + pos ++; + + // padding to next multiple of 4 + pos = Math.ceil( pos / 4 ) * 4; + + values = copyFromBuffer( buffer, arrayType, pos, cardinality * valuesNumber, bigEndian ); + + pos += arrayType.BYTES_PER_ELEMENT * cardinality * valuesNumber; + + attributes[ attributeName ] = { + type: attributeType, + cardinality: cardinality, + values: values + }; + + } + + pos = Math.ceil( pos / 4 ) * 4; + + indices = null; + + if ( indexedGeometry ) { + + indices = copyFromBuffer( + buffer, + indicesType === 1 ? Uint32Array : Uint16Array, + pos, + indicesNumber, + bigEndian + ); + + } + + return { + version: version, + attributes: attributes, + indices: indices + }; + + } + + // Define the public interface + + THREE.PRWMLoader = function PRWMLoader( manager ) { + + this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; + + }; + + THREE.PRWMLoader.prototype = { + + constructor: THREE.PRWMLoader, + + load: function ( url, onLoad, onProgress, onError ) { + + var scope = this; + + var loader = new THREE.FileLoader( scope.manager ); + loader.setResponseType( 'arraybuffer' ); + + url = url.replace( /\*/g, isBigEndianPlatform() ? 'be' : 'le' ); + + loader.load( url, function ( arrayBuffer ) { + + onLoad( scope.parse( arrayBuffer ) ); + + }, onProgress, onError ); + + }, + + parse: function ( arrayBuffer ) { + + console.time( 'PRWMLoader' ); + + var data = decodePrwm( arrayBuffer ), + attributesKey = Object.keys( data.attributes ), + bufferGeometry = new THREE.BufferGeometry(), + attribute, + i; + + for ( i = 0; i < attributesKey.length; i ++ ) { + + attribute = data.attributes[ attributesKey[ i ] ]; + bufferGeometry.addAttribute( attributesKey[ i ], new THREE.BufferAttribute( attribute.values, attribute.cardinality, attribute.normalized ) ); + + } + + if ( data.indices !== null ) { + + bufferGeometry.setIndex( new THREE.BufferAttribute( data.indices, 1 ) ); + + } + + console.timeEnd( 'PRWMLoader' ); + + return bufferGeometry; + + } + + }; + + THREE.PRWMLoader.isBigEndianPlatform = function () { + + return isBigEndianPlatform(); + + }; + +} )( THREE ); diff --git a/examples/models/prwm/faceted-nefertiti.be.prwm b/examples/models/prwm/faceted-nefertiti.be.prwm new file mode 100644 index 0000000000000000000000000000000000000000..31fa2f53c791a1469157afc927d65e801e9d219b Binary files /dev/null and b/examples/models/prwm/faceted-nefertiti.be.prwm differ diff --git a/examples/models/prwm/faceted-nefertiti.le.prwm b/examples/models/prwm/faceted-nefertiti.le.prwm new file mode 100644 index 0000000000000000000000000000000000000000..3d36aea7a17332a6a981439c44547771a5d38a35 Binary files /dev/null and b/examples/models/prwm/faceted-nefertiti.le.prwm differ diff --git a/examples/models/prwm/smooth-suzanne.be.prwm b/examples/models/prwm/smooth-suzanne.be.prwm new file mode 100644 index 0000000000000000000000000000000000000000..64003330fb1a87066a80c7c2bb682da5cc430e5b Binary files /dev/null and b/examples/models/prwm/smooth-suzanne.be.prwm differ diff --git a/examples/models/prwm/smooth-suzanne.le.prwm b/examples/models/prwm/smooth-suzanne.le.prwm new file mode 100644 index 0000000000000000000000000000000000000000..8f59db2d82c43799259806ecfd29d0b08e1b52ea Binary files /dev/null and b/examples/models/prwm/smooth-suzanne.le.prwm differ diff --git a/examples/models/prwm/vive-controller.be.prwm b/examples/models/prwm/vive-controller.be.prwm new file mode 100644 index 0000000000000000000000000000000000000000..4aacc70be35eafb9ca0575080fb437ca70e0f015 Binary files /dev/null and b/examples/models/prwm/vive-controller.be.prwm differ diff --git a/examples/models/prwm/vive-controller.le.prwm b/examples/models/prwm/vive-controller.le.prwm new file mode 100644 index 0000000000000000000000000000000000000000..92597bc7ca216f718d21f066db1f0dd2e32aa3a6 Binary files /dev/null and b/examples/models/prwm/vive-controller.le.prwm differ diff --git a/examples/webgl_loader_prwm.html b/examples/webgl_loader_prwm.html new file mode 100644 index 0000000000000000000000000000000000000000..fa311a9e29034c8e80269fdb338cf0d1f8865ae9 --- /dev/null +++ b/examples/webgl_loader_prwm.html @@ -0,0 +1,250 @@ + + + + three.js webgl - loaders - PRWM loader + + + + + + + + +
+ Models + Faceted Nefertiti + Smooth Suzanne + Vive Controller +
+
+ The parsing of PRWM file is especially fast when the endianness of the file is the same as the endianness + of the client platform. The loader will automatically replace the * in the model url + by either le or be depending on the client platform's endianness to + download the most appropriate file.

+ This platform endianness is .

+ See your console for stats.

+ Specifications and implementations +
+ + + + + + + +