Spaces:
Running
Running
; | |
/** | |
* 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 | |
*/ | |
THREE.DRACOExporter = function () {}; | |
THREE.DRACOExporter.prototype = { | |
constructor: THREE.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: THREE.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 THREE.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 THREE.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 | |
THREE.DRACOExporter.MESH_EDGEBREAKER_ENCODING = 1; | |
THREE.DRACOExporter.MESH_SEQUENTIAL_ENCODING = 0; | |
// Geometry type | |
THREE.DRACOExporter.POINT_CLOUD = 0; | |
THREE.DRACOExporter.TRIANGULAR_MESH = 1; | |
// Attribute type | |
THREE.DRACOExporter.INVALID = - 1; | |
THREE.DRACOExporter.POSITION = 0; | |
THREE.DRACOExporter.NORMAL = 1; | |
THREE.DRACOExporter.COLOR = 2; | |
THREE.DRACOExporter.TEX_COORD = 3; | |
THREE.DRACOExporter.GENERIC = 4; | |