瀏覽代碼

JSM: Added module and TS file for DRACOExporter.

Mugen87 6 年之前
父節點
當前提交
615bb9451b

+ 1 - 0
docs/manual/en/introduction/Import-via-modules.html

@@ -124,6 +124,7 @@
 				<li>exporters
 					<ul>
 						<li>ColladaExporter</li>
+						<li>DRACOExporter</li>
 						<li>GLTFExporter</li>
 						<li>MMDExporter</li>
 						<li>OBJExporter</li>

+ 3 - 3
examples/js/exporters/DracoExporter.js

@@ -1,5 +1,3 @@
-'use strict';
-
 /**
  * Export draco compressed files from threejs geometry objects.
  *
@@ -17,6 +15,8 @@
  * @author tentone
  */
 
+/* global DracoEncoderModule */
+
 THREE.DRACOExporter = function () {};
 
 THREE.DRACOExporter.prototype = {
@@ -78,7 +78,7 @@ THREE.DRACOExporter.prototype = {
 
 		} else {
 
-			var faces = new ( vertices.count > 65535 ? Uint32Array : Uint16Array ) ( vertices.count );
+			var faces = new ( vertices.count > 65535 ? Uint32Array : Uint16Array )( vertices.count );
 
 			for ( var i = 0; i < faces.length; i ++ ) {
 

+ 20 - 0
examples/jsm/exporters/DRACOExporter.d.ts

@@ -0,0 +1,20 @@
+import {
+  BufferGeometry,
+  Geometry
+} from '../../../src/Three';
+
+export interface DRACOExporterOptions {
+  decodeSpeed?: number;
+  encodeSpeed?: number;
+  encoderMethod?: number;
+  quantization?: number[];
+  exportUvs?: boolean;
+  exportNormals?: boolean;
+  exportColor?: boolean;
+}
+
+export class DRACOExporter {
+  constructor();
+
+  parse(geometry: BufferGeometry, options: DRACOExporterOptions): Int8Array;
+}

+ 212 - 0
examples/jsm/exporters/DRACOExporter.js

@@ -0,0 +1,212 @@
+/**
+ * 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 };

+ 1 - 0
utils/modularize.js

@@ -41,6 +41,7 @@ var files = [
 	{ path: 'effects/StereoEffect.js', dependencies: [], ignoreList: [] },
 
 	{ path: 'exporters/ColladaExporter.js', dependencies: [], ignoreList: [] },
+	{ path: 'exporters/DRACOExporter.js', dependencies: [], ignoreList: [ 'Geometry' ] },
 	{ path: 'exporters/GLTFExporter.js', dependencies: [], ignoreList: [ 'AnimationClip', 'Camera', 'Geometry', 'Material', 'Mesh', 'Object3D', 'RGBFormat', 'Scenes', 'ShaderMaterial', 'VertexColors' ] },
 	{ path: 'exporters/MMDExporter.js', dependencies: [], ignoreList: [] },
 	{ path: 'exporters/OBJExporter.js', dependencies: [], ignoreList: [] },