/** * SEA3D - Google Draco * @author Sunag / http://www.sunag.com.br/ */ 'use strict'; // // Lossy Compression // SEA3D.GeometryDraco = function ( name, data, sea3d ) { this.name = name; this.data = data; this.sea3d = sea3d; var attrib = data.readUShort(), i; this.isBig = ( attrib & 1 ) !== 0; data.readVInt = this.isBig ? data.readUInt : data.readUShort; this.groups = []; if ( attrib & 32 ) { this.uv = []; this.uv.length = data.readUByte(); } if ( attrib & 1024 ) { var numGroups = data.readUByte(), groupOffset = 0; for ( i = 0; i < numGroups; i ++ ) { var groupLength = data.readVInt() * 3; this.groups.push( { start: groupOffset, count: groupLength, } ); groupOffset += groupLength; } } var module = SEA3D.GeometryDraco.getModule(), dracoData = new Int8Array( data.concat( data.position, data.bytesAvailable ).buffer ); var decoder = new module.Decoder(); var buffer = new module.DecoderBuffer(); buffer.Init( dracoData, dracoData.length ); var mesh = new module.Mesh(); var decodingStatus = decoder.DecodeBufferToMesh( buffer, mesh ); if ( ! decodingStatus.ok() ) { data.position += 5; // jump "DRACO" magic string var version = data.readUByte() + '.' + data.readUByte(); // draco version console.error( "SEA3D Draco", version, "decoding failed:", decodingStatus.error_msg(), "You may need update 'draco_decoder.js'." ); // use an empty geometry this.vertex = new Float32Array(); return; } var index = 0; this.vertex = this.readFloat32Array( module, decoder, mesh, index ++ ); if ( attrib & 4 ) this.normal = this.readFloat32Array( module, decoder, mesh, index ++ ); if ( attrib & 32 ) { for ( i = 0; i < this.uv.length; i ++ ) { this.uv[ i ] = this.readFloat32Array( module, decoder, mesh, index ++ ); } } if ( attrib & 64 ) { this.jointPerVertex = decoder.GetAttribute( mesh, index ).num_components(); this.joint = this.readUint16Array( module, decoder, mesh, index ++ ); this.weight = this.readFloat32Array( module, decoder, mesh, index ++ ); } this.indexes = this.readIndices( module, decoder, mesh ); module.destroy( mesh ); module.destroy( buffer ); module.destroy( decoder ); }; SEA3D.GeometryDraco.getModule = function () { if ( ! this.module ) { this.module = DracoDecoderModule(); } return this.module; }; SEA3D.GeometryDraco.prototype.type = "sdrc"; SEA3D.GeometryDraco.prototype.readIndices = function ( module, decoder, mesh ) { var numFaces = mesh.num_faces(), numIndices = numFaces * 3, indices = new ( numIndices >= 0xFFFE ? Uint32Array : Uint16Array )( numIndices ); var ia = new module.DracoInt32Array(); for ( var i = 0; i < numFaces; ++ i ) { decoder.GetFaceFromMesh( mesh, i, ia ); var index = i * 3; indices[ index ] = ia.GetValue( 0 ); indices[ index + 1 ] = ia.GetValue( 1 ); indices[ index + 2 ] = ia.GetValue( 2 ); } module.destroy( ia ); return indices; }; SEA3D.GeometryDraco.prototype.readFloat32Array = function ( module, decoder, mesh, attrib ) { var attribute = decoder.GetAttribute( mesh, attrib ), numPoints = mesh.num_points(); var dracoArray = new module.DracoFloat32Array(); decoder.GetAttributeFloatForAllPoints( mesh, attribute, dracoArray ); var size = numPoints * attribute.num_components(), output = new Float32Array( size ); for ( var i = 0; i < size; ++ i ) { output[ i ] = dracoArray.GetValue( i ); } module.destroy( dracoArray ); return output; }; SEA3D.GeometryDraco.prototype.readUint16Array = function ( module, decoder, mesh, attrib, type ) { var attribute = decoder.GetAttribute( mesh, attrib ), numPoints = mesh.num_points(); var dracoArray = new module.DracoUInt16Array(); decoder.GetAttributeUInt16ForAllPoints( mesh, attribute, dracoArray ); var size = numPoints * attribute.num_components(), output = new Uint16Array( size ); for ( var i = 0; i < size; ++ i ) { output[ i ] = dracoArray.GetValue( i ); } module.destroy( dracoArray ); return output; }; // // Extension // THREE.SEA3D.EXTENSIONS_LOADER.push( { setTypeRead: function () { this.file.addClass( SEA3D.GeometryDraco, true ); this.file.typeRead[ SEA3D.GeometryDraco.prototype.type ] = this.readGeometryBuffer; } } );