/** * Export draco compressed files from threejs geometry objects. * * Draco files are compressed and usually are smaller than conventional 3D file formats. * * The exporter receives a options object containing * - decodeSpeed, indicates how to tune the encoder regarding decode speed (0 gives better speed but worst quality) * - encodeSpeed, indicates how to tune the encoder parameters (0 gives better speed but worst quality) * - encoderMethod * - quantization, indicates the presision of each type of data stored in the draco file in the order (POSITION, NORMAL, COLOR, TEX_COORD, GENERIC) * - exportUvs * - exportNormals * * @class DRACOExporter * @author tentone */ import { BufferGeometry } from "../../../build/three.module.js"; /* global DracoEncoderModule */ var DRACOExporter = function () {}; DRACOExporter.prototype = { constructor: DRACOExporter, parse: function ( geometry, options ) { if ( DracoEncoderModule === undefined ) { throw new Error( 'THREE.DRACOExporter: required the draco_decoder to work.' ); } if ( options === undefined ) { options = { decodeSpeed: 5, encodeSpeed: 5, encoderMethod: DRACOExporter.MESH_EDGEBREAKER_ENCODING, quantization: [ 16, 8, 8, 8, 8 ], exportUvs: true, exportNormals: true, exportColor: false, }; } var dracoEncoder = DracoEncoderModule(); var encoder = new dracoEncoder.Encoder(); var builder = new dracoEncoder.MeshBuilder(); var mesh = new dracoEncoder.Mesh(); if ( geometry.isGeometry === true ) { var bufferGeometry = new BufferGeometry(); bufferGeometry.fromGeometry( geometry ); geometry = bufferGeometry; } if ( geometry.isBufferGeometry !== true ) { throw new Error( 'THREE.DRACOExporter.parse(geometry, options): geometry is not a THREE.Geometry or BufferGeometry instance.' ); } var vertices = geometry.getAttribute( 'position' ); builder.AddFloatAttributeToMesh( mesh, dracoEncoder.POSITION, vertices.count, vertices.itemSize, vertices.array ); var faces = geometry.getIndex(); if ( faces !== null ) { builder.AddFacesToMesh( mesh, faces.count, faces.array ); } else { var faces = new ( vertices.count > 65535 ? Uint32Array : Uint16Array )( vertices.count ); for ( var i = 0; i < faces.length; i ++ ) { faces[ i ] = i; } builder.AddFacesToMesh( mesh, vertices.count, faces ); } if ( options.exportNormals === true ) { var normals = geometry.getAttribute( 'normal' ); if ( normals !== undefined ) { builder.AddFloatAttributeToMesh( mesh, dracoEncoder.NORMAL, normals.count, normals.itemSize, normals.array ); } } if ( options.exportUvs === true ) { var uvs = geometry.getAttribute( 'uv' ); if ( uvs !== undefined ) { builder.AddFloatAttributeToMesh( mesh, dracoEncoder.TEX_COORD, uvs.count, uvs.itemSize, uvs.array ); } } if ( options.exportColor === true ) { var colors = geometry.getAttribute( 'color' ); if ( colors !== undefined ) { builder.AddFloatAttributeToMesh( mesh, dracoEncoder.COLOR, colors.count, colors.itemSize, colors.array ); } } //Compress using draco encoder var encodedData = new dracoEncoder.DracoInt8Array(); //Sets the desired encoding and decoding speed for the given options from 0 (slowest speed, but the best compression) to 10 (fastest, but the worst compression). encoder.SetSpeedOptions( options.encodeSpeed || 5, options.decodeSpeed || 5 ); // Sets the desired encoding method for a given geometry. if ( options.encoderMethod !== undefined ) { encoder.SetEncodingMethod( options.encoderMethod ); } // Sets the quantization (number of bits used to represent) compression options for a named attribute. // The attribute values will be quantized in a box defined by the maximum extent of the attribute values. if ( options.quantization !== undefined ) { for ( var i = 0; i < 5; i ++ ) { if ( options.quantization[ i ] !== undefined ) { encoder.SetAttributeQuantization( i, options.quantization[ i ] ); } } } var length = encoder.EncodeMeshToDracoBuffer( mesh, encodedData ); dracoEncoder.destroy( mesh ); if ( length === 0 ) { throw new Error( 'THREE.DRACOExporter: Draco encoding failed.' ); } //Copy encoded data to buffer. var outputData = new Int8Array( new ArrayBuffer( length ) ); for ( var i = 0; i < length; i ++ ) { outputData[ i ] = encodedData.GetValue( i ); } dracoEncoder.destroy( encodedData ); dracoEncoder.destroy( encoder ); dracoEncoder.destroy( builder ); return outputData; } }; // Encoder methods DRACOExporter.MESH_EDGEBREAKER_ENCODING = 1; DRACOExporter.MESH_SEQUENTIAL_ENCODING = 0; // Geometry type DRACOExporter.POINT_CLOUD = 0; DRACOExporter.TRIANGULAR_MESH = 1; // Attribute type DRACOExporter.INVALID = - 1; DRACOExporter.POSITION = 0; DRACOExporter.NORMAL = 1; DRACOExporter.COLOR = 2; DRACOExporter.TEX_COORD = 3; DRACOExporter.GENERIC = 4; export { DRACOExporter };