|
@@ -1,723 +1,626 @@
|
|
|
-/** Copyright 2016 The Draco Authors.
|
|
|
- *
|
|
|
- * Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
- * you may not use this file except in compliance with the License.
|
|
|
- * You may obtain a copy of the License at
|
|
|
- *
|
|
|
- * http://www.apache.org/licenses/LICENSE-2.0
|
|
|
- *
|
|
|
- * Unless required by applicable law or agreed to in writing, software
|
|
|
- * distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
- * See the License for the specific language governing permissions and
|
|
|
- * limitations under the License.
|
|
|
- */
|
|
|
-
|
|
|
/**
|
|
|
- * @param {THREE.LoadingManager} manager
|
|
|
+ * @author Don McCurdy / https://www.donmccurdy.com
|
|
|
*/
|
|
|
+
|
|
|
THREE.DRACOLoader = function ( manager ) {
|
|
|
|
|
|
- this.timeLoaded = 0;
|
|
|
this.manager = manager || THREE.DefaultLoadingManager;
|
|
|
- this.materials = null;
|
|
|
- this.verbosity = 0;
|
|
|
- this.attributeOptions = {};
|
|
|
- this.drawMode = THREE.TrianglesDrawMode;
|
|
|
- // Native Draco attribute type to Three.JS attribute type.
|
|
|
- this.nativeAttributeMap = {
|
|
|
- position: "POSITION",
|
|
|
- normal: "NORMAL",
|
|
|
- color: "COLOR",
|
|
|
- uv: "TEX_COORD"
|
|
|
+
|
|
|
+ this.path = '';
|
|
|
+ this.crossOrigin = 'anonymous';
|
|
|
+
|
|
|
+ this.decoderPath = '';
|
|
|
+ this.decoderConfig = {};
|
|
|
+ this.decoderBinary = null;
|
|
|
+ this.decoderPending = null;
|
|
|
+
|
|
|
+ this.workerLimit = 4;
|
|
|
+ this.workerPool = [];
|
|
|
+ this.workerNextTaskID = 1;
|
|
|
+ this.workerSourceURL = '';
|
|
|
+
|
|
|
+ this.defaultAttributeIDs = {
|
|
|
+ position: 'POSITION',
|
|
|
+ normal: 'NORMAL',
|
|
|
+ color: 'COLOR',
|
|
|
+ uv: 'TEX_COORD'
|
|
|
+ };
|
|
|
+ this.defaultAttributeTypes = {
|
|
|
+ position: 'Float32Array',
|
|
|
+ normal: 'Float32Array',
|
|
|
+ color: 'Float32Array',
|
|
|
+ uv: 'Float32Array'
|
|
|
};
|
|
|
|
|
|
};
|
|
|
|
|
|
THREE.DRACOLoader.prototype = {
|
|
|
- constructor: THREE.DRACOLoader,
|
|
|
|
|
|
- load: function ( url, onLoad, onProgress, onError ) {
|
|
|
+ constructor: THREE.DRACOLoader,
|
|
|
|
|
|
- var scope = this;
|
|
|
- var loader = new THREE.FileLoader( scope.manager );
|
|
|
- loader.setPath( this.path );
|
|
|
- loader.setResponseType( "arraybuffer" );
|
|
|
- loader.load(
|
|
|
- url,
|
|
|
- function ( blob ) {
|
|
|
+ setPath: function ( path ) {
|
|
|
|
|
|
- scope.decodeDracoFile( blob, onLoad );
|
|
|
+ this.path = path;
|
|
|
|
|
|
- },
|
|
|
- onProgress,
|
|
|
- onError
|
|
|
- );
|
|
|
+ return this;
|
|
|
|
|
|
},
|
|
|
|
|
|
- setPath: function ( value ) {
|
|
|
+ setCrossOrigin: function ( crossOrigin ) {
|
|
|
+
|
|
|
+ this.crossOrigin = crossOrigin;
|
|
|
|
|
|
- this.path = value;
|
|
|
return this;
|
|
|
|
|
|
},
|
|
|
|
|
|
- setVerbosity: function ( level ) {
|
|
|
+ setDecoderPath: function ( path ) {
|
|
|
+
|
|
|
+ this.decoderPath = path;
|
|
|
|
|
|
- this.verbosity = level;
|
|
|
return this;
|
|
|
|
|
|
},
|
|
|
|
|
|
- /**
|
|
|
- * Sets desired mode for generated geometry indices.
|
|
|
- * Can be either:
|
|
|
- * THREE.TrianglesDrawMode
|
|
|
- * THREE.TriangleStripDrawMode
|
|
|
- */
|
|
|
- setDrawMode: function ( drawMode ) {
|
|
|
+ setDecoderConfig: function ( config ) {
|
|
|
+
|
|
|
+ this.decoderConfig = config;
|
|
|
|
|
|
- this.drawMode = drawMode;
|
|
|
return this;
|
|
|
|
|
|
},
|
|
|
|
|
|
- /**
|
|
|
- * Skips dequantization for a specific attribute.
|
|
|
- * |attributeName| is the THREE.js name of the given attribute type.
|
|
|
- * The only currently supported |attributeName| is 'position', more may be
|
|
|
- * added in future.
|
|
|
- */
|
|
|
- setSkipDequantization: function ( attributeName, skip ) {
|
|
|
-
|
|
|
- var skipDequantization = true;
|
|
|
- if ( typeof skip !== "undefined" ) skipDequantization = skip;
|
|
|
- this.getAttributeOptions(
|
|
|
- attributeName
|
|
|
- ).skipDequantization = skipDequantization;
|
|
|
+ setWorkerLimit: function ( workerLimit ) {
|
|
|
+
|
|
|
+ this.workerLimit = workerLimit;
|
|
|
+
|
|
|
return this;
|
|
|
|
|
|
},
|
|
|
|
|
|
- /**
|
|
|
- * Decompresses a Draco buffer. Names of attributes (for ID and type maps)
|
|
|
- * must be one of the supported three.js types, including: position, color,
|
|
|
- * normal, uv, uv2, skinIndex, skinWeight.
|
|
|
- *
|
|
|
- * @param {ArrayBuffer} rawBuffer
|
|
|
- * @param {Function} callback
|
|
|
- * @param {Object|undefined} attributeUniqueIdMap Provides a pre-defined ID
|
|
|
- * for each attribute in the geometry to be decoded. If given,
|
|
|
- * `attributeTypeMap` is required and `nativeAttributeMap` will be
|
|
|
- * ignored.
|
|
|
- * @param {Object|undefined} attributeTypeMap Provides a predefined data
|
|
|
- * type (as a typed array constructor) for each attribute in the
|
|
|
- * geometry to be decoded.
|
|
|
- */
|
|
|
- decodeDracoFile: function (
|
|
|
- rawBuffer,
|
|
|
- callback,
|
|
|
- attributeUniqueIdMap,
|
|
|
- attributeTypeMap
|
|
|
- ) {
|
|
|
-
|
|
|
- var scope = this;
|
|
|
- THREE.DRACOLoader.getDecoderModule().then( function ( module ) {
|
|
|
-
|
|
|
- scope.decodeDracoFileInternal(
|
|
|
- rawBuffer,
|
|
|
- module.decoder,
|
|
|
- callback,
|
|
|
- attributeUniqueIdMap,
|
|
|
- attributeTypeMap
|
|
|
- );
|
|
|
+ /** @deprecated */
|
|
|
+ setVerbosity: function () {
|
|
|
|
|
|
- } );
|
|
|
+ console.warn( 'THREE.DRACOLoader: The .setVerbosity() method has been removed.' );
|
|
|
|
|
|
},
|
|
|
|
|
|
- decodeDracoFileInternal: function (
|
|
|
- rawBuffer,
|
|
|
- dracoDecoder,
|
|
|
- callback,
|
|
|
- attributeUniqueIdMap,
|
|
|
- attributeTypeMap
|
|
|
- ) {
|
|
|
+ /** @deprecated */
|
|
|
+ setDrawMode: function () {
|
|
|
|
|
|
- /*
|
|
|
- * Here is how to use Draco Javascript decoder and get the geometry.
|
|
|
- */
|
|
|
- var buffer = new dracoDecoder.DecoderBuffer();
|
|
|
- buffer.Init( new Int8Array( rawBuffer ), rawBuffer.byteLength );
|
|
|
- var decoder = new dracoDecoder.Decoder();
|
|
|
+ console.warn( 'THREE.DRACOLoader: The .setDrawMode() method has been removed.' );
|
|
|
|
|
|
- /*
|
|
|
- * Determine what type is this file: mesh or point cloud.
|
|
|
- */
|
|
|
- var geometryType = decoder.GetEncodedGeometryType( buffer );
|
|
|
- if ( geometryType == dracoDecoder.TRIANGULAR_MESH ) {
|
|
|
-
|
|
|
- if ( this.verbosity > 0 ) {
|
|
|
+ },
|
|
|
|
|
|
- console.log( "Loaded a mesh." );
|
|
|
+ /** @deprecated */
|
|
|
+ setSkipDequantization: function () {
|
|
|
|
|
|
- }
|
|
|
+ console.warn( 'THREE.DRACOLoader: The .setSkipDequantization() method has been removed.' );
|
|
|
|
|
|
- } else if ( geometryType == dracoDecoder.POINT_CLOUD ) {
|
|
|
+ },
|
|
|
|
|
|
- if ( this.verbosity > 0 ) {
|
|
|
+ load: function ( url, onLoad, onProgress, onError ) {
|
|
|
|
|
|
- console.log( "Loaded a point cloud." );
|
|
|
+ var loader = new THREE.FileLoader( this.manager );
|
|
|
|
|
|
- }
|
|
|
+ loader.setPath( this.path );
|
|
|
+ loader.setResponseType( 'arraybuffer' );
|
|
|
|
|
|
- } else {
|
|
|
+ if ( this.crossOrigin === 'use-credentials' ) {
|
|
|
|
|
|
- var errorMsg = "THREE.DRACOLoader: Unknown geometry type.";
|
|
|
- console.error( errorMsg );
|
|
|
- throw new Error( errorMsg );
|
|
|
+ loader.setWithCredentials( true );
|
|
|
|
|
|
}
|
|
|
- callback(
|
|
|
- this.convertDracoGeometryTo3JS(
|
|
|
- dracoDecoder,
|
|
|
- decoder,
|
|
|
- geometryType,
|
|
|
- buffer,
|
|
|
- attributeUniqueIdMap,
|
|
|
- attributeTypeMap
|
|
|
- )
|
|
|
- );
|
|
|
+
|
|
|
+ loader.load( url, ( buffer ) => {
|
|
|
+
|
|
|
+ var taskConfig = {
|
|
|
+ attributeIDs: this.defaultAttributeIDs,
|
|
|
+ attributeTypes: this.defaultAttributeTypes
|
|
|
+ };
|
|
|
+
|
|
|
+ this.decodeGeometry( buffer, taskConfig )
|
|
|
+ .then( onLoad )
|
|
|
+ .catch( onError );
|
|
|
+
|
|
|
+ }, onProgress, onError );
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ /** @deprecated Kept for backward-compatibility with previous DRACOLoader versions. */
|
|
|
+ decodeDracoFile: function ( buffer, callback, attributeIDs, attributeTypes ) {
|
|
|
+
|
|
|
+ var taskConfig = {
|
|
|
+ attributeIDs: attributeIDs || this.defaultAttributeIDs,
|
|
|
+ attributeTypes: attributeTypes || this.defaultAttributeTypes
|
|
|
+ };
|
|
|
+
|
|
|
+ this.decodeGeometry( buffer, taskConfig ).then( callback );
|
|
|
|
|
|
},
|
|
|
|
|
|
- addAttributeToGeometry: function (
|
|
|
- dracoDecoder,
|
|
|
- decoder,
|
|
|
- dracoGeometry,
|
|
|
- attributeName,
|
|
|
- attributeType,
|
|
|
- attribute,
|
|
|
- geometry,
|
|
|
- geometryBuffer
|
|
|
- ) {
|
|
|
+ decodeGeometry: function ( buffer, taskConfig ) {
|
|
|
|
|
|
- if ( attribute.ptr === 0 ) {
|
|
|
+ var worker;
|
|
|
+ var taskID = this.workerNextTaskID ++;
|
|
|
+ var taskCost = buffer.byteLength;
|
|
|
|
|
|
- var errorMsg = "THREE.DRACOLoader: No attribute " + attributeName;
|
|
|
- console.error( errorMsg );
|
|
|
- throw new Error( errorMsg );
|
|
|
+ // TODO: For backward-compatibility, support 'attributeTypes' objects containing
|
|
|
+ // references (rather than names) to typed array constructors. These must be
|
|
|
+ // serialized before sending them to the worker.
|
|
|
+ for ( var attribute in taskConfig.attributeTypes ) {
|
|
|
+
|
|
|
+ var type = taskConfig.attributeTypes[ attribute ];
|
|
|
+
|
|
|
+ if ( type.BYTES_PER_ELEMENT !== undefined ) {
|
|
|
+
|
|
|
+ taskConfig.attributeTypes[ attribute ] = type.name;
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
- var numComponents = attribute.num_components();
|
|
|
- var numPoints = dracoGeometry.num_points();
|
|
|
- var numValues = numPoints * numComponents;
|
|
|
- var attributeData;
|
|
|
- var TypedBufferAttribute;
|
|
|
+ // Obtain a worker and assign a task, and construct a geometry instance
|
|
|
+ // when the task completes.
|
|
|
+ var geometryPending = this._getWorker( taskID, taskCost )
|
|
|
+ .then( ( _worker ) => {
|
|
|
|
|
|
- switch ( attributeType ) {
|
|
|
+ worker = _worker;
|
|
|
|
|
|
- case Float32Array:
|
|
|
- attributeData = new dracoDecoder.DracoFloat32Array();
|
|
|
- decoder.GetAttributeFloatForAllPoints(
|
|
|
- dracoGeometry,
|
|
|
- attribute,
|
|
|
- attributeData
|
|
|
- );
|
|
|
- geometryBuffer[ attributeName ] = new Float32Array( numValues );
|
|
|
- TypedBufferAttribute = THREE.Float32BufferAttribute;
|
|
|
- break;
|
|
|
+ return new Promise( ( resolve, reject ) => {
|
|
|
|
|
|
- case Int8Array:
|
|
|
- attributeData = new dracoDecoder.DracoInt8Array();
|
|
|
- decoder.GetAttributeInt8ForAllPoints(
|
|
|
- dracoGeometry,
|
|
|
- attribute,
|
|
|
- attributeData
|
|
|
- );
|
|
|
- geometryBuffer[ attributeName ] = new Int8Array( numValues );
|
|
|
- TypedBufferAttribute = THREE.Int8BufferAttribute;
|
|
|
- break;
|
|
|
+ worker._callbacks[ taskID ] = { resolve, reject };
|
|
|
|
|
|
- case Int16Array:
|
|
|
- attributeData = new dracoDecoder.DracoInt16Array();
|
|
|
- decoder.GetAttributeInt16ForAllPoints(
|
|
|
- dracoGeometry,
|
|
|
- attribute,
|
|
|
- attributeData
|
|
|
- );
|
|
|
- geometryBuffer[ attributeName ] = new Int16Array( numValues );
|
|
|
- TypedBufferAttribute = THREE.Int16BufferAttribute;
|
|
|
- break;
|
|
|
+ worker.postMessage( { type: 'decode', id: taskID, taskConfig, buffer }, [ buffer ] );
|
|
|
|
|
|
- case Int32Array:
|
|
|
- attributeData = new dracoDecoder.DracoInt32Array();
|
|
|
- decoder.GetAttributeInt32ForAllPoints(
|
|
|
- dracoGeometry,
|
|
|
- attribute,
|
|
|
- attributeData
|
|
|
- );
|
|
|
- geometryBuffer[ attributeName ] = new Int32Array( numValues );
|
|
|
- TypedBufferAttribute = THREE.Int32BufferAttribute;
|
|
|
- break;
|
|
|
+ // this.debug();
|
|
|
|
|
|
- case Uint8Array:
|
|
|
- attributeData = new dracoDecoder.DracoUInt8Array();
|
|
|
- decoder.GetAttributeUInt8ForAllPoints(
|
|
|
- dracoGeometry,
|
|
|
- attribute,
|
|
|
- attributeData
|
|
|
- );
|
|
|
- geometryBuffer[ attributeName ] = new Uint8Array( numValues );
|
|
|
- TypedBufferAttribute = THREE.Uint8BufferAttribute;
|
|
|
- break;
|
|
|
+ } );
|
|
|
|
|
|
- case Uint16Array:
|
|
|
- attributeData = new dracoDecoder.DracoUInt16Array();
|
|
|
- decoder.GetAttributeUInt16ForAllPoints(
|
|
|
- dracoGeometry,
|
|
|
- attribute,
|
|
|
- attributeData
|
|
|
- );
|
|
|
- geometryBuffer[ attributeName ] = new Uint16Array( numValues );
|
|
|
- TypedBufferAttribute = THREE.Uint16BufferAttribute;
|
|
|
- break;
|
|
|
+ } )
|
|
|
+ .then( ( message ) => this._createGeometry( message.geometry ) );
|
|
|
|
|
|
- case Uint32Array:
|
|
|
- attributeData = new dracoDecoder.DracoUInt32Array();
|
|
|
- decoder.GetAttributeUInt32ForAllPoints(
|
|
|
- dracoGeometry,
|
|
|
- attribute,
|
|
|
- attributeData
|
|
|
- );
|
|
|
- geometryBuffer[ attributeName ] = new Uint32Array( numValues );
|
|
|
- TypedBufferAttribute = THREE.Uint32BufferAttribute;
|
|
|
- break;
|
|
|
+ // Remove task from the task list.
|
|
|
+ geometryPending
|
|
|
+ .finally( () => {
|
|
|
|
|
|
- default:
|
|
|
- var errorMsg = "THREE.DRACOLoader: Unexpected attribute type.";
|
|
|
- console.error( errorMsg );
|
|
|
- throw new Error( errorMsg );
|
|
|
+ if ( worker && taskID ) {
|
|
|
|
|
|
- }
|
|
|
+ this._releaseTask( worker, taskID );
|
|
|
|
|
|
- // Copy data from decoder.
|
|
|
- for ( var i = 0; i < numValues; i ++ ) {
|
|
|
+ // this.debug();
|
|
|
|
|
|
- geometryBuffer[ attributeName ][ i ] = attributeData.GetValue( i );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
- // Add attribute to THREEJS geometry for rendering.
|
|
|
- geometry.addAttribute(
|
|
|
- attributeName,
|
|
|
- new TypedBufferAttribute( geometryBuffer[ attributeName ], numComponents )
|
|
|
- );
|
|
|
- dracoDecoder.destroy( attributeData );
|
|
|
+ } );
|
|
|
+
|
|
|
+ return geometryPending;
|
|
|
|
|
|
},
|
|
|
|
|
|
- convertDracoGeometryTo3JS: function (
|
|
|
- dracoDecoder,
|
|
|
- decoder,
|
|
|
- geometryType,
|
|
|
- buffer,
|
|
|
- attributeUniqueIdMap,
|
|
|
- attributeTypeMap
|
|
|
- ) {
|
|
|
+ _createGeometry: function ( geometryData ) {
|
|
|
+
|
|
|
+ var geometry = new THREE.BufferGeometry();
|
|
|
|
|
|
- // TODO: Should not assume native Draco attribute IDs apply.
|
|
|
- if ( this.getAttributeOptions( "position" ).skipDequantization === true ) {
|
|
|
+ if ( geometryData.index ) {
|
|
|
|
|
|
- decoder.SkipAttributeTransform( dracoDecoder.POSITION );
|
|
|
+ geometry.setIndex( new THREE.BufferAttribute( geometryData.index.array, 1 ) );
|
|
|
|
|
|
}
|
|
|
- var dracoGeometry;
|
|
|
- var decodingStatus;
|
|
|
- var start_time = performance.now();
|
|
|
- if ( geometryType === dracoDecoder.TRIANGULAR_MESH ) {
|
|
|
|
|
|
- dracoGeometry = new dracoDecoder.Mesh();
|
|
|
- decodingStatus = decoder.DecodeBufferToMesh( buffer, dracoGeometry );
|
|
|
+ for ( var i = 0; i < geometryData.attributes.length; i++ ) {
|
|
|
|
|
|
- } else {
|
|
|
+ var attribute = geometryData.attributes[ i ];
|
|
|
+ var name = attribute.name;
|
|
|
+ var array = attribute.array;
|
|
|
+ var itemSize = attribute.itemSize;
|
|
|
|
|
|
- dracoGeometry = new dracoDecoder.PointCloud();
|
|
|
- decodingStatus = decoder.DecodeBufferToPointCloud( buffer, dracoGeometry );
|
|
|
+ geometry.addAttribute( name, new THREE.BufferAttribute( array, itemSize ) );
|
|
|
|
|
|
}
|
|
|
- if ( ! decodingStatus.ok() || dracoGeometry.ptr == 0 ) {
|
|
|
|
|
|
- var errorMsg = "THREE.DRACOLoader: Decoding failed: ";
|
|
|
- errorMsg += decodingStatus.error_msg();
|
|
|
- console.error( errorMsg );
|
|
|
- dracoDecoder.destroy( decoder );
|
|
|
- dracoDecoder.destroy( dracoGeometry );
|
|
|
- throw new Error( errorMsg );
|
|
|
+ return geometry;
|
|
|
|
|
|
- }
|
|
|
+ },
|
|
|
|
|
|
- var decode_end = performance.now();
|
|
|
- dracoDecoder.destroy( buffer );
|
|
|
- /*
|
|
|
- * Example on how to retrieve mesh and attributes.
|
|
|
- */
|
|
|
- var numFaces;
|
|
|
- if ( geometryType == dracoDecoder.TRIANGULAR_MESH ) {
|
|
|
+ _loadLibrary: function ( url, responseType ) {
|
|
|
|
|
|
- numFaces = dracoGeometry.num_faces();
|
|
|
- if ( this.verbosity > 0 ) {
|
|
|
+ var loader = new THREE.FileLoader( this.manager );
|
|
|
+ loader.setPath( this.decoderPath );
|
|
|
+ loader.setResponseType( responseType );
|
|
|
|
|
|
- console.log( "Number of faces loaded: " + numFaces.toString() );
|
|
|
+ return new Promise( ( resolve, reject ) => {
|
|
|
|
|
|
- }
|
|
|
+ loader.load( url, resolve, undefined, reject );
|
|
|
+
|
|
|
+ } );
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ _initDecoder: function () {
|
|
|
+
|
|
|
+ if ( this.decoderPending ) return this.decoderPending;
|
|
|
+
|
|
|
+ var useJS = typeof WebAssembly !== 'object' || this.decoderConfig.type === 'js';
|
|
|
+ var librariesPending = [];
|
|
|
+
|
|
|
+ if ( useJS ) {
|
|
|
+
|
|
|
+ librariesPending.push( this._loadLibrary( 'draco_decoder.js', 'text' ) );
|
|
|
|
|
|
} else {
|
|
|
|
|
|
- numFaces = 0;
|
|
|
+ librariesPending.push( this._loadLibrary( 'draco_wasm_wrapper.js', 'text' ) );
|
|
|
+ librariesPending.push( this._loadLibrary( 'draco_decoder.wasm', 'arraybuffer' ) );
|
|
|
|
|
|
}
|
|
|
|
|
|
- var numPoints = dracoGeometry.num_points();
|
|
|
- var numAttributes = dracoGeometry.num_attributes();
|
|
|
- if ( this.verbosity > 0 ) {
|
|
|
+ this.decoderPending = Promise.all( librariesPending )
|
|
|
+ .then( ( libraries ) => {
|
|
|
|
|
|
- console.log( "Number of points loaded: " + numPoints.toString() );
|
|
|
- console.log( "Number of attributes loaded: " + numAttributes.toString() );
|
|
|
+ var jsContent = libraries[ 0 ];
|
|
|
|
|
|
- }
|
|
|
+ if ( ! useJS ) {
|
|
|
|
|
|
- // Verify if there is position attribute.
|
|
|
- // TODO: Should not assume native Draco attribute IDs apply.
|
|
|
- var posAttId = decoder.GetAttributeId( dracoGeometry, dracoDecoder.POSITION );
|
|
|
- if ( posAttId == - 1 ) {
|
|
|
+ this.decoderConfig.wasmBinary = libraries[ 1 ];
|
|
|
|
|
|
- var errorMsg = "THREE.DRACOLoader: No position attribute found.";
|
|
|
- console.error( errorMsg );
|
|
|
- dracoDecoder.destroy( decoder );
|
|
|
- dracoDecoder.destroy( dracoGeometry );
|
|
|
- throw new Error( errorMsg );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
- var posAttribute = decoder.GetAttribute( dracoGeometry, posAttId );
|
|
|
+ var fn = THREE.DRACOLoader.DRACOWorker.toString();
|
|
|
|
|
|
- // Structure for converting to THREEJS geometry later.
|
|
|
- var geometryBuffer = {};
|
|
|
- // Import data to Three JS geometry.
|
|
|
- var geometry = new THREE.BufferGeometry();
|
|
|
+ var body = [
|
|
|
+ '/* draco decoder */',
|
|
|
+ jsContent,
|
|
|
+ '',
|
|
|
+ '/* worker */',
|
|
|
+ fn.substring( fn.indexOf( '{' ) + 1, fn.lastIndexOf( '}' ) )
|
|
|
+ ].join( '\n' );
|
|
|
|
|
|
- // Do not use both the native attribute map and a provided (e.g. glTF) map.
|
|
|
- if ( attributeUniqueIdMap ) {
|
|
|
-
|
|
|
- // Add attributes of user specified unique id. E.g. GLTF models.
|
|
|
- for ( var attributeName in attributeUniqueIdMap ) {
|
|
|
-
|
|
|
- var attributeType = attributeTypeMap[ attributeName ];
|
|
|
- var attributeId = attributeUniqueIdMap[ attributeName ];
|
|
|
- var attribute = decoder.GetAttributeByUniqueId(
|
|
|
- dracoGeometry,
|
|
|
- attributeId
|
|
|
- );
|
|
|
- this.addAttributeToGeometry(
|
|
|
- dracoDecoder,
|
|
|
- decoder,
|
|
|
- dracoGeometry,
|
|
|
- attributeName,
|
|
|
- attributeType,
|
|
|
- attribute,
|
|
|
- geometry,
|
|
|
- geometryBuffer
|
|
|
- );
|
|
|
+ this.workerSourceURL = URL.createObjectURL( new Blob( [ body ] ) );
|
|
|
|
|
|
- }
|
|
|
+ } );
|
|
|
|
|
|
- } else {
|
|
|
+ return this.decoderPending;
|
|
|
|
|
|
- // Add native Draco attribute type to geometry.
|
|
|
- for ( var attributeName in this.nativeAttributeMap ) {
|
|
|
+ },
|
|
|
|
|
|
- var attId = decoder.GetAttributeId(
|
|
|
- dracoGeometry,
|
|
|
- dracoDecoder[ this.nativeAttributeMap[ attributeName ] ]
|
|
|
- );
|
|
|
- if ( attId !== - 1 ) {
|
|
|
+ _getWorker: function ( taskID, taskCost ) {
|
|
|
|
|
|
- if ( this.verbosity > 0 ) {
|
|
|
+ return this._initDecoder().then( () => {
|
|
|
|
|
|
- console.log( "Loaded " + attributeName + " attribute." );
|
|
|
+ if ( this.workerPool.length < this.workerLimit ) {
|
|
|
|
|
|
- }
|
|
|
- var attribute = decoder.GetAttribute( dracoGeometry, attId );
|
|
|
- this.addAttributeToGeometry(
|
|
|
- dracoDecoder,
|
|
|
- decoder,
|
|
|
- dracoGeometry,
|
|
|
- attributeName,
|
|
|
- Float32Array,
|
|
|
- attribute,
|
|
|
- geometry,
|
|
|
- geometryBuffer
|
|
|
- );
|
|
|
+ var worker = new Worker( this.workerSourceURL );
|
|
|
|
|
|
- }
|
|
|
+ worker._callbacks = {};
|
|
|
+ worker._taskCosts = {};
|
|
|
+ worker._taskLoad = 0;
|
|
|
|
|
|
- }
|
|
|
+ worker.postMessage( { type: 'init', decoderConfig: this.decoderConfig } );
|
|
|
|
|
|
- }
|
|
|
+ worker.onmessage = function ( e ) {
|
|
|
|
|
|
- // For mesh, we need to generate the faces.
|
|
|
- if ( geometryType == dracoDecoder.TRIANGULAR_MESH ) {
|
|
|
+ var message = e.data;
|
|
|
|
|
|
- if ( this.drawMode === THREE.TriangleStripDrawMode ) {
|
|
|
+ switch ( message.type ) {
|
|
|
|
|
|
- var stripsArray = new dracoDecoder.DracoInt32Array();
|
|
|
- decoder.GetTriangleStripsFromMesh(
|
|
|
- dracoGeometry,
|
|
|
- stripsArray
|
|
|
- );
|
|
|
- geometryBuffer.indices = new Uint32Array( stripsArray.size() );
|
|
|
- for ( var i = 0; i < stripsArray.size(); ++ i ) {
|
|
|
+ case 'decode':
|
|
|
+ worker._callbacks[ message.id ].resolve( message );
|
|
|
+ break;
|
|
|
|
|
|
- geometryBuffer.indices[ i ] = stripsArray.GetValue( i );
|
|
|
+ case 'error':
|
|
|
+ worker._callbacks[ message.id ].reject( message );
|
|
|
+ break;
|
|
|
|
|
|
- }
|
|
|
- dracoDecoder.destroy( stripsArray );
|
|
|
+ default:
|
|
|
+ console.error( 'THREE.DRACOLoader: Unexpected message, "' + message.type + '"' );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ this.workerPool.push( worker );
|
|
|
|
|
|
} else {
|
|
|
|
|
|
- var numIndices = numFaces * 3;
|
|
|
- geometryBuffer.indices = new Uint32Array( numIndices );
|
|
|
- var ia = new dracoDecoder.DracoInt32Array();
|
|
|
- for ( var i = 0; i < numFaces; ++ i ) {
|
|
|
+ this.workerPool.sort( function ( a, b ) {
|
|
|
|
|
|
- decoder.GetFaceFromMesh( dracoGeometry, i, ia );
|
|
|
- var index = i * 3;
|
|
|
- geometryBuffer.indices[ index ] = ia.GetValue( 0 );
|
|
|
- geometryBuffer.indices[ index + 1 ] = ia.GetValue( 1 );
|
|
|
- geometryBuffer.indices[ index + 2 ] = ia.GetValue( 2 );
|
|
|
+ return a._taskLoad > b._taskLoad ? - 1 : 1;
|
|
|
|
|
|
- }
|
|
|
- dracoDecoder.destroy( ia );
|
|
|
+ } );
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ var worker = this.workerPool[ this.workerPool.length - 1 ];
|
|
|
+ worker._taskCosts[ taskID ] = taskCost;
|
|
|
+ worker._taskLoad += taskCost;
|
|
|
+ return worker;
|
|
|
+
|
|
|
+ } );
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ _releaseTask: function ( worker, taskID ) {
|
|
|
+
|
|
|
+ worker._taskLoad -= worker._taskCosts[ taskID ];
|
|
|
+ delete worker._callbacks[ taskID ];
|
|
|
+ delete worker._taskCosts[ taskID ];
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ debug: function () {
|
|
|
|
|
|
- geometry.drawMode = this.drawMode;
|
|
|
- if ( geometryType == dracoDecoder.TRIANGULAR_MESH ) {
|
|
|
+ console.log( 'Task load: ', this.workerPool.map( ( worker ) => worker._taskLoad ) );
|
|
|
|
|
|
- geometry.setIndex(
|
|
|
- new ( geometryBuffer.indices.length > 65535
|
|
|
- ? THREE.Uint32BufferAttribute
|
|
|
- : THREE.Uint16BufferAttribute )( geometryBuffer.indices, 1 )
|
|
|
- );
|
|
|
+ },
|
|
|
+
|
|
|
+ dispose: function () {
|
|
|
+
|
|
|
+ for ( var i = 0; i < this.workerPool.length; ++ i ) {
|
|
|
+
|
|
|
+ this.workerPool[ i ].terminate();
|
|
|
|
|
|
}
|
|
|
|
|
|
- // TODO: Should not assume native Draco attribute IDs apply.
|
|
|
- // TODO: Can other attribute types be quantized?
|
|
|
- var posTransform = new dracoDecoder.AttributeQuantizationTransform();
|
|
|
- if ( posTransform.InitFromAttribute( posAttribute ) ) {
|
|
|
-
|
|
|
- // Quantized attribute. Store the quantization parameters into the
|
|
|
- // THREE.js attribute.
|
|
|
- geometry.attributes[ "position" ].isQuantized = true;
|
|
|
- geometry.attributes[ "position" ].maxRange = posTransform.range();
|
|
|
- geometry.attributes[
|
|
|
- "position"
|
|
|
- ].numQuantizationBits = posTransform.quantization_bits();
|
|
|
- geometry.attributes[ "position" ].minValues = new Float32Array( 3 );
|
|
|
- for ( var i = 0; i < 3; ++ i ) {
|
|
|
-
|
|
|
- geometry.attributes[ "position" ].minValues[ i ] = posTransform.min_value(
|
|
|
- i
|
|
|
- );
|
|
|
+ this.workerPool.length = 0;
|
|
|
|
|
|
- }
|
|
|
+ return this;
|
|
|
+
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+/* WEB WORKER */
|
|
|
+
|
|
|
+THREE.DRACOLoader.DRACOWorker = function () {
|
|
|
+
|
|
|
+ var decoderConfig;
|
|
|
+ var decoderPending;
|
|
|
+
|
|
|
+ onmessage = function ( e ) {
|
|
|
+
|
|
|
+ var message = e.data;
|
|
|
+
|
|
|
+ switch ( message.type ) {
|
|
|
+
|
|
|
+ case 'init':
|
|
|
+ decoderConfig = message.decoderConfig;
|
|
|
+ decoderPending = new Promise( function ( resolve, reject ) {
|
|
|
+
|
|
|
+ decoderConfig.onModuleLoaded = function ( draco ) {
|
|
|
+
|
|
|
+ // Module is Promise-like. Wrap before resolving to avoid loop.
|
|
|
+ resolve( { draco: draco } );
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ DracoDecoderModule( decoderConfig );
|
|
|
+
|
|
|
+ } );
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'decode':
|
|
|
+ var buffer = message.buffer;
|
|
|
+ var taskConfig = message.taskConfig;
|
|
|
+ decoderPending.then( ( module ) => {
|
|
|
+
|
|
|
+ var draco = module.draco;
|
|
|
+ var decoder = new draco.Decoder();
|
|
|
+ var decoderBuffer = new draco.DecoderBuffer();
|
|
|
+ decoderBuffer.Init( new Int8Array( buffer ), buffer.byteLength );
|
|
|
+
|
|
|
+ try {
|
|
|
+
|
|
|
+ var geometry = decodeGeometry( draco, decoder, decoderBuffer, taskConfig );
|
|
|
+
|
|
|
+ var buffers = geometry.attributes.map( ( attr ) => attr.array.buffer );
|
|
|
+
|
|
|
+ if ( geometry.index ) buffers.push( geometry.index.array.buffer );
|
|
|
+
|
|
|
+ self.postMessage( { type: 'decode', id: message.id, geometry }, buffers );
|
|
|
+
|
|
|
+ } catch ( error ) {
|
|
|
+
|
|
|
+ console.error( error );
|
|
|
+
|
|
|
+ self.postMessage( { type: 'error', id: message.id, error: error.message } );
|
|
|
+
|
|
|
+ } finally {
|
|
|
+
|
|
|
+ draco.destroy( decoderBuffer );
|
|
|
+ draco.destroy( decoder );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ } );
|
|
|
+ break;
|
|
|
|
|
|
}
|
|
|
- dracoDecoder.destroy( posTransform );
|
|
|
- dracoDecoder.destroy( decoder );
|
|
|
- dracoDecoder.destroy( dracoGeometry );
|
|
|
|
|
|
- this.decode_time = decode_end - start_time;
|
|
|
- this.import_time = performance.now() - decode_end;
|
|
|
+ };
|
|
|
+
|
|
|
+ function decodeGeometry( draco, decoder, decoderBuffer, taskConfig ) {
|
|
|
+
|
|
|
+ var attributeIDs = taskConfig.attributeIDs;
|
|
|
+ var attributeTypes = taskConfig.attributeTypes;
|
|
|
+
|
|
|
+ var dracoGeometry;
|
|
|
+ var decodingStatus;
|
|
|
|
|
|
- if ( this.verbosity > 0 ) {
|
|
|
+ var geometryType = decoder.GetEncodedGeometryType( decoderBuffer );
|
|
|
|
|
|
- console.log( "Decode time: " + this.decode_time );
|
|
|
- console.log( "Import time: " + this.import_time );
|
|
|
+ if ( geometryType === draco.TRIANGULAR_MESH ) {
|
|
|
+
|
|
|
+ dracoGeometry = new draco.Mesh();
|
|
|
+ decodingStatus = decoder.DecodeBufferToMesh( decoderBuffer, dracoGeometry );
|
|
|
+
|
|
|
+ } else if ( geometryType === draco.POINT_CLOUD ) {
|
|
|
+
|
|
|
+ dracoGeometry = new draco.PointCloud();
|
|
|
+ decodingStatus = decoder.DecodeBufferToPointCloud( decoderBuffer, dracoGeometry );
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ throw new Error( 'THREE.DRACOLoader: Unexpected geometry type.' );
|
|
|
|
|
|
}
|
|
|
- return geometry;
|
|
|
|
|
|
- },
|
|
|
+ if ( ! decodingStatus.ok() || dracoGeometry.ptr === 0 ) {
|
|
|
|
|
|
- isVersionSupported: function ( version, callback ) {
|
|
|
+ throw new Error( 'THREE.DRACOLoader: Decoding failed: ' + decodingStatus.error_msg() );
|
|
|
|
|
|
- THREE.DRACOLoader.getDecoderModule().then( function ( module ) {
|
|
|
+ }
|
|
|
|
|
|
- callback( module.decoder.isVersionSupported( version ) );
|
|
|
+ var geometry = { index: null, attributes: [] };
|
|
|
|
|
|
- } );
|
|
|
+ var numPoints = dracoGeometry.num_points();
|
|
|
+ var numAttributes = dracoGeometry.num_attributes();
|
|
|
|
|
|
- },
|
|
|
+ // Add attributes of user specified unique id.
|
|
|
+ for (var attributeName in attributeIDs) {
|
|
|
|
|
|
- getAttributeOptions: function ( attributeName ) {
|
|
|
+ var attributeType = self[ attributeTypes[ attributeName ] ];
|
|
|
+ var attributeId = attributeIDs[ attributeName ];
|
|
|
+ var attribute = decoder.GetAttributeByUniqueId( dracoGeometry, attributeId );
|
|
|
|
|
|
- if ( typeof this.attributeOptions[ attributeName ] === "undefined" )
|
|
|
- this.attributeOptions[ attributeName ] = {};
|
|
|
- return this.attributeOptions[ attributeName ];
|
|
|
+ geometry.attributes.push( decodeAttribute( draco, decoder, dracoGeometry, attributeName, attributeType, attribute ) );
|
|
|
|
|
|
- }
|
|
|
-};
|
|
|
+ }
|
|
|
|
|
|
-THREE.DRACOLoader.decoderPath = "./";
|
|
|
-THREE.DRACOLoader.decoderConfig = {};
|
|
|
-THREE.DRACOLoader.decoderModulePromise = null;
|
|
|
+ // Add index.
|
|
|
+ if ( geometryType === draco.TRIANGULAR_MESH ) {
|
|
|
|
|
|
-/**
|
|
|
- * Sets the base path for decoder source files.
|
|
|
- * @param {string} path
|
|
|
- */
|
|
|
-THREE.DRACOLoader.setDecoderPath = function ( path ) {
|
|
|
+ // Generate mesh faces.
|
|
|
+ var numFaces = dracoGeometry.num_faces();
|
|
|
+ var numIndices = numFaces * 3;
|
|
|
+ var index = new Uint32Array( numIndices );
|
|
|
+ var indexArray = new draco.DracoInt32Array();
|
|
|
|
|
|
- THREE.DRACOLoader.decoderPath = path;
|
|
|
+ for ( var i = 0; i < numFaces; ++ i ) {
|
|
|
|
|
|
-};
|
|
|
+ decoder.GetFaceFromMesh( dracoGeometry, i, indexArray );
|
|
|
|
|
|
-/**
|
|
|
- * Sets decoder configuration and releases singleton decoder module. Module
|
|
|
- * will be recreated with the next decoding call.
|
|
|
- * @param {Object} config
|
|
|
- */
|
|
|
-THREE.DRACOLoader.setDecoderConfig = function ( config ) {
|
|
|
+ for ( var j = 0; j < 3; ++ j ) {
|
|
|
|
|
|
- var wasmBinary = THREE.DRACOLoader.decoderConfig.wasmBinary;
|
|
|
- THREE.DRACOLoader.decoderConfig = config || {};
|
|
|
- THREE.DRACOLoader.releaseDecoderModule();
|
|
|
+ index[ i * 3 + j ] = indexArray.GetValue( j );
|
|
|
|
|
|
- // Reuse WASM binary.
|
|
|
- if ( wasmBinary ) THREE.DRACOLoader.decoderConfig.wasmBinary = wasmBinary;
|
|
|
+ }
|
|
|
|
|
|
-};
|
|
|
+ }
|
|
|
|
|
|
-/**
|
|
|
- * Releases the singleton DracoDecoderModule instance. Module will be recreated
|
|
|
- * with the next decoding call.
|
|
|
- */
|
|
|
-THREE.DRACOLoader.releaseDecoderModule = function () {
|
|
|
+ geometry.index = { array: index, itemSize: 1 };
|
|
|
|
|
|
- THREE.DRACOLoader.decoderModulePromise = null;
|
|
|
+ draco.destroy( indexArray );
|
|
|
|
|
|
-};
|
|
|
+ }
|
|
|
|
|
|
-/**
|
|
|
- * Gets WebAssembly or asm.js singleton instance of DracoDecoderModule
|
|
|
- * after testing for browser support. Returns Promise that resolves when
|
|
|
- * module is available.
|
|
|
- * @return {Promise<{decoder: DracoDecoderModule}>}
|
|
|
- */
|
|
|
-THREE.DRACOLoader.getDecoderModule = function () {
|
|
|
+ draco.destroy( dracoGeometry );
|
|
|
|
|
|
- var scope = this;
|
|
|
- var path = THREE.DRACOLoader.decoderPath;
|
|
|
- var config = THREE.DRACOLoader.decoderConfig;
|
|
|
- var promise = THREE.DRACOLoader.decoderModulePromise;
|
|
|
+ return geometry;
|
|
|
|
|
|
- if ( promise ) return promise;
|
|
|
+ };
|
|
|
|
|
|
- // Load source files.
|
|
|
- if ( typeof DracoDecoderModule !== "undefined" ) {
|
|
|
+ function decodeAttribute ( draco, decoder, dracoGeometry, attributeName, attributeType, attribute ) {
|
|
|
|
|
|
- // Loaded externally.
|
|
|
- promise = Promise.resolve();
|
|
|
+ var numComponents = attribute.num_components();
|
|
|
+ var numPoints = dracoGeometry.num_points();
|
|
|
+ var numValues = numPoints * numComponents;
|
|
|
+ var dracoArray;
|
|
|
|
|
|
- } else if ( typeof WebAssembly !== "object" || config.type === "js" ) {
|
|
|
+ var array;
|
|
|
|
|
|
- // Load with asm.js.
|
|
|
- promise = THREE.DRACOLoader._loadScript( path + "draco_decoder.js" );
|
|
|
+ switch ( attributeType ) {
|
|
|
|
|
|
- } else {
|
|
|
+ case Float32Array:
|
|
|
+ dracoArray = new draco.DracoFloat32Array();
|
|
|
+ decoder.GetAttributeFloatForAllPoints( dracoGeometry, attribute, dracoArray );
|
|
|
+ array = new Float32Array( numValues );
|
|
|
+ break;
|
|
|
|
|
|
- // Load with WebAssembly.
|
|
|
- config.wasmBinaryFile = path + "draco_decoder.wasm";
|
|
|
- promise = THREE.DRACOLoader._loadScript( path + "draco_wasm_wrapper.js" )
|
|
|
- .then( function () {
|
|
|
+ case Int8Array:
|
|
|
+ dracoArray = new draco.DracoInt8Array();
|
|
|
+ decoder.GetAttributeInt8ForAllPoints( dracoGeometry, attribute, dracoArray );
|
|
|
+ array = new Int8Array( numValues );
|
|
|
+ break;
|
|
|
|
|
|
- return THREE.DRACOLoader._loadArrayBuffer( config.wasmBinaryFile );
|
|
|
+ case Int16Array:
|
|
|
+ dracoArray = new draco.DracoInt16Array();
|
|
|
+ decoder.GetAttributeInt16ForAllPoints( dracoGeometry, attribute, dracoArray );
|
|
|
+ array = new Int16Array( numValues );
|
|
|
+ break;
|
|
|
|
|
|
- } )
|
|
|
- .then( function ( wasmBinary ) {
|
|
|
+ case Int32Array:
|
|
|
+ dracoArray = new draco.DracoInt32Array();
|
|
|
+ decoder.GetAttributeInt32ForAllPoints( dracoGeometry, attribute, dracoArray );
|
|
|
+ array = new Int32Array( numValues );
|
|
|
+ break;
|
|
|
|
|
|
- config.wasmBinary = wasmBinary;
|
|
|
+ case Uint8Array:
|
|
|
+ dracoArray = new draco.DracoUInt8Array();
|
|
|
+ decoder.GetAttributeUInt8ForAllPoints( dracoGeometry, attribute, dracoArray );
|
|
|
+ array = new Uint8Array( numValues );
|
|
|
+ break;
|
|
|
|
|
|
- } );
|
|
|
+ case Uint16Array:
|
|
|
+ dracoArray = new draco.DracoUInt16Array();
|
|
|
+ decoder.GetAttributeUInt16ForAllPoints( dracoGeometry, attribute, dracoArray );
|
|
|
+ array = new Uint16Array( numValues );
|
|
|
+ break;
|
|
|
|
|
|
- }
|
|
|
+ case Uint32Array:
|
|
|
+ dracoArray = new draco.DracoUInt32Array();
|
|
|
+ decoder.GetAttributeUInt32ForAllPoints( dracoGeometry, attribute, dracoArray );
|
|
|
+ array = new Uint32Array( numValues );
|
|
|
+ break;
|
|
|
|
|
|
- // Wait for source files, then create and return a decoder.
|
|
|
- promise = promise.then( function () {
|
|
|
+ default:
|
|
|
+ throw new Error( 'THREE.DRACOLoader: Unexpected attribute type.' );
|
|
|
|
|
|
- return new Promise( function ( resolve ) {
|
|
|
+ }
|
|
|
|
|
|
- config.onModuleLoaded = function ( decoder ) {
|
|
|
+ for ( var i = 0; i < numValues; i++ ) {
|
|
|
|
|
|
- scope.timeLoaded = performance.now();
|
|
|
- // Module is Promise-like. Wrap before resolving to avoid loop.
|
|
|
- resolve( { decoder: decoder } );
|
|
|
+ array[ i ] = dracoArray.GetValue( i );
|
|
|
|
|
|
- };
|
|
|
- DracoDecoderModule( config );
|
|
|
+ }
|
|
|
|
|
|
- } );
|
|
|
+ draco.destroy( dracoArray );
|
|
|
|
|
|
- } );
|
|
|
+ return {
|
|
|
+ name: attributeName,
|
|
|
+ array: array,
|
|
|
+ itemSize: numComponents
|
|
|
+ };
|
|
|
|
|
|
- THREE.DRACOLoader.decoderModulePromise = promise;
|
|
|
- return promise;
|
|
|
+ };
|
|
|
|
|
|
};
|
|
|
|
|
|
-/**
|
|
|
- * @param {string} src
|
|
|
- * @return {Promise}
|
|
|
- */
|
|
|
-THREE.DRACOLoader._loadScript = function ( src ) {
|
|
|
+/** Deprecated static methods */
|
|
|
|
|
|
- var prevScript = document.getElementById( "decoder_script" );
|
|
|
- if ( prevScript !== null ) {
|
|
|
+/** @deprecated */
|
|
|
+THREE.DRACOLoader.setDecoderPath = function () {
|
|
|
|
|
|
- prevScript.parentNode.removeChild( prevScript );
|
|
|
+ console.warn( 'THREE.DRACOLoader: The .setDecoderPath() method has been removed. Use instance methods.' );
|
|
|
|
|
|
- }
|
|
|
- var head = document.getElementsByTagName( "head" )[ 0 ];
|
|
|
- var script = document.createElement( "script" );
|
|
|
- script.id = "decoder_script";
|
|
|
- script.type = "text/javascript";
|
|
|
- script.src = src;
|
|
|
- return new Promise( function ( resolve ) {
|
|
|
+};
|
|
|
|
|
|
- script.onload = resolve;
|
|
|
- head.appendChild( script );
|
|
|
+/** @deprecated */
|
|
|
+THREE.DRACOLoader.setDecoderConfig = function () {
|
|
|
|
|
|
- } );
|
|
|
+ console.warn( 'THREE.DRACOLoader: The .setDecoderConfig() method has been removed. Use instance methods.' );
|
|
|
|
|
|
};
|
|
|
|
|
|
-/**
|
|
|
- * @param {string} src
|
|
|
- * @return {Promise}
|
|
|
- */
|
|
|
-THREE.DRACOLoader._loadArrayBuffer = function ( src ) {
|
|
|
+/** @deprecated */
|
|
|
+THREE.DRACOLoader.releaseDecoderModule = function () {
|
|
|
|
|
|
- var loader = new THREE.FileLoader();
|
|
|
- loader.setResponseType( "arraybuffer" );
|
|
|
- return new Promise( function ( resolve, reject ) {
|
|
|
+ console.warn( 'THREE.DRACOLoader: The .releaseDecoderModule() method has been removed. Use instance methods.' );
|
|
|
|
|
|
- loader.load( src, resolve, undefined, reject );
|
|
|
+};
|
|
|
+
|
|
|
+/** @deprecated */
|
|
|
+THREE.DRACOLoader.getDecoderModule = function () {
|
|
|
|
|
|
- } );
|
|
|
+ console.warn( 'THREE.DRACOLoader: The .getDecoderModule() method has been removed. Use instance methods.' );
|
|
|
|
|
|
};
|