mirror of
https://git.mirrors.martin98.com/https://github.com/google/draco
synced 2025-09-13 00:53:13 +08:00
DRACOLoader: Simplify decoder source loading. (#315)
* DRACOLoader: Simplify decoder source loading.
This commit is contained in:
parent
64e9192d43
commit
3ea3cd8b20
@ -14,26 +14,16 @@
|
|||||||
//
|
//
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// |dracoPath| sets the path for the Draco decoder source files. The default
|
/**
|
||||||
// path is "./". If |dracoDecoderType|.type is set to "js", then DRACOLoader
|
* @param {THREE.LoadingManager} manager
|
||||||
// will load the Draco JavaScript decoder.
|
*/
|
||||||
THREE.DRACOLoader = function(dracoPath, dracoDecoderType, manager) {
|
THREE.DRACOLoader = function(manager) {
|
||||||
this.timeLoaded = 0;
|
this.timeLoaded = 0;
|
||||||
this.manager = (manager !== undefined) ? manager :
|
this.manager = manager || THREE.DefaultLoadingManager;
|
||||||
THREE.DefaultLoadingManager;
|
|
||||||
this.materials = null;
|
this.materials = null;
|
||||||
this.verbosity = 0;
|
this.verbosity = 0;
|
||||||
this.attributeOptions = {};
|
this.attributeOptions = {};
|
||||||
if (dracoDecoderType !== undefined) {
|
|
||||||
THREE.DRACOLoader.dracoDecoderType = dracoDecoderType;
|
|
||||||
}
|
|
||||||
this.drawMode = THREE.TrianglesDrawMode;
|
this.drawMode = THREE.TrianglesDrawMode;
|
||||||
this.dracoSrcPath = (dracoPath !== undefined) ? dracoPath : './';
|
|
||||||
// If draco_decoder.js or wasm code is already loaded/included, then do
|
|
||||||
// not dynamically load the decoder.
|
|
||||||
if (typeof DracoDecoderModule === 'undefined') {
|
|
||||||
THREE.DRACOLoader.loadDracoDecoder(this);
|
|
||||||
}
|
|
||||||
// User defined unique id for attributes.
|
// User defined unique id for attributes.
|
||||||
this.attributeUniqueIdMap = {};
|
this.attributeUniqueIdMap = {};
|
||||||
// Native Draco attribute type to Three.JS attribute type.
|
// Native Draco attribute type to Three.JS attribute type.
|
||||||
@ -45,8 +35,6 @@ THREE.DRACOLoader = function(dracoPath, dracoDecoderType, manager) {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
THREE.DRACOLoader.dracoDecoderType = {};
|
|
||||||
|
|
||||||
THREE.DRACOLoader.prototype = {
|
THREE.DRACOLoader.prototype = {
|
||||||
|
|
||||||
constructor: THREE.DRACOLoader,
|
constructor: THREE.DRACOLoader,
|
||||||
@ -116,11 +104,10 @@ THREE.DRACOLoader.prototype = {
|
|||||||
*/
|
*/
|
||||||
decodeDracoFile: function(rawBuffer, callback, attributeUniqueIdMap) {
|
decodeDracoFile: function(rawBuffer, callback, attributeUniqueIdMap) {
|
||||||
var scope = this;
|
var scope = this;
|
||||||
this.attributeUniqueIdMap = (attributeUniqueIdMap !== undefined) ?
|
this.attributeUniqueIdMap = attributeUniqueIdMap || {};
|
||||||
attributeUniqueIdMap : {};
|
THREE.DRACOLoader.getDecoderModule()
|
||||||
THREE.DRACOLoader.getDecoderModule(
|
.then( function ( module ) {
|
||||||
function(dracoDecoder) {
|
scope.decodeDracoFileInternal( rawBuffer, module.decoder, callback );
|
||||||
scope.decodeDracoFileInternal(rawBuffer, dracoDecoder, callback);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -333,9 +320,9 @@ THREE.DRACOLoader.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
isVersionSupported: function(version, callback) {
|
isVersionSupported: function(version, callback) {
|
||||||
THREE.DRACOLoader.getDecoderModule(
|
THREE.DRACOLoader.getDecoderModule()
|
||||||
function(decoder) {
|
.then( function ( module ) {
|
||||||
callback(decoder.isVersionSupported(version));
|
callback( module.decoder.isVersionSupported( version ) );
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -346,131 +333,117 @@ THREE.DRACOLoader.prototype = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// This function loads a JavaScript file and adds it to the page. "path"
|
THREE.DRACOLoader.decoderPath = './';
|
||||||
// is the path to the JavaScript file. "onLoadFunc" is the function to be
|
THREE.DRACOLoader.decoderConfig = {};
|
||||||
// called when the JavaScript file has been loaded.
|
THREE.DRACOLoader.decoderModulePromise = null;
|
||||||
THREE.DRACOLoader.loadJavaScriptFile = function(path, onLoadFunc,
|
|
||||||
dracoDecoder) {
|
|
||||||
var previous_decoder_script = document.getElementById("decoder_script");
|
|
||||||
if (previous_decoder_script !== null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var head = document.getElementsByTagName('head')[0];
|
|
||||||
var element = document.createElement('script');
|
|
||||||
element.id = "decoder_script";
|
|
||||||
element.type = 'text/javascript';
|
|
||||||
element.src = path;
|
|
||||||
if (onLoadFunc !== null) {
|
|
||||||
element.onload = onLoadFunc(dracoDecoder);
|
|
||||||
} else {
|
|
||||||
element.onload = function(dracoDecoder) {
|
|
||||||
THREE.DRACOLoader.timeLoaded = performance.now();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
head.appendChild(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
THREE.DRACOLoader.loadWebAssemblyDecoder = function(dracoDecoder) {
|
|
||||||
THREE.DRACOLoader.dracoDecoderType['wasmBinaryFile'] =
|
|
||||||
dracoDecoder.dracoSrcPath + 'draco_decoder.wasm';
|
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
xhr.open('GET', dracoDecoder.dracoSrcPath + 'draco_decoder.wasm', true);
|
|
||||||
xhr.responseType = 'arraybuffer';
|
|
||||||
xhr.onload = function() {
|
|
||||||
// draco_wasm_wrapper.js must be loaded before DracoDecoderModule is
|
|
||||||
// created. The object passed into DracoDecoderModule() must contain a
|
|
||||||
// property with the name of wasmBinary and the value must be an
|
|
||||||
// ArrayBuffer containing the contents of the .wasm file.
|
|
||||||
THREE.DRACOLoader.dracoDecoderType['wasmBinary'] = xhr.response;
|
|
||||||
THREE.DRACOLoader.timeLoaded = performance.now();
|
|
||||||
};
|
|
||||||
xhr.send(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function will test if the browser has support for WebAssembly. If
|
|
||||||
// it does it will download the WebAssembly Draco decoder, if not it will
|
|
||||||
// download the asmjs Draco decoder.
|
|
||||||
THREE.DRACOLoader.loadDracoDecoder = function(dracoDecoder) {
|
|
||||||
if (typeof WebAssembly !== 'object' ||
|
|
||||||
THREE.DRACOLoader.dracoDecoderType.type === 'js') {
|
|
||||||
// No WebAssembly support
|
|
||||||
THREE.DRACOLoader.loadJavaScriptFile(dracoDecoder.dracoSrcPath +
|
|
||||||
'draco_decoder.js', null, dracoDecoder);
|
|
||||||
} else {
|
|
||||||
THREE.DRACOLoader.loadJavaScriptFile(dracoDecoder.dracoSrcPath +
|
|
||||||
'draco_wasm_wrapper.js',
|
|
||||||
function (dracoDecoder) {
|
|
||||||
THREE.DRACOLoader.loadWebAssemblyDecoder(dracoDecoder);
|
|
||||||
}, dracoDecoder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
THREE.DRACOLoader.decoderCreationCalled = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates and returns a singleton instance of the DracoDecoderModule.
|
* Sets the base path for decoder source files.
|
||||||
* The module loading is done asynchronously for WebAssembly. Initialized module
|
* @param {string} path
|
||||||
* can be accessed through the callback function
|
|
||||||
* |onDracoDecoderModuleLoadedCallback|.
|
|
||||||
*/
|
*/
|
||||||
THREE.DRACOLoader.getDecoderModule = (function() {
|
THREE.DRACOLoader.setDecoderPath = function ( path ) {
|
||||||
return function(onDracoDecoderModuleLoadedCallback) {
|
THREE.DRACOLoader.decoderPath = path;
|
||||||
if (typeof THREE.DRACOLoader.decoderModule !== 'undefined') {
|
|
||||||
// Module already initialized.
|
|
||||||
if (typeof onDracoDecoderModuleLoadedCallback !== 'undefined') {
|
|
||||||
onDracoDecoderModuleLoadedCallback(THREE.DRACOLoader.decoderModule);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (typeof DracoDecoderModule === 'undefined') {
|
|
||||||
// Wait until the Draco decoder is loaded before starting the error
|
|
||||||
// timer.
|
|
||||||
if (THREE.DRACOLoader.timeLoaded > 0) {
|
|
||||||
var waitMs = performance.now() - THREE.DRACOLoader.timeLoaded;
|
|
||||||
|
|
||||||
// After loading the Draco JavaScript decoder file, there is still
|
|
||||||
// some time before the DracoDecoderModule is defined. So start a
|
|
||||||
// loop to check when the DracoDecoderModule gets defined. If the
|
|
||||||
// time is hit throw an error.
|
|
||||||
if (waitMs > 5000) {
|
|
||||||
throw new Error(
|
|
||||||
'THREE.DRACOLoader: DracoDecoderModule not found.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!THREE.DRACOLoader.decoderCreationCalled) {
|
|
||||||
THREE.DRACOLoader.decoderCreationCalled = true;
|
|
||||||
THREE.DRACOLoader.dracoDecoderType['onModuleLoaded'] =
|
|
||||||
function(module) {
|
|
||||||
THREE.DRACOLoader.decoderModule = module;
|
|
||||||
};
|
|
||||||
DracoDecoderModule(THREE.DRACOLoader.dracoDecoderType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Either the DracoDecoderModule has not been defined or the decoder
|
|
||||||
// has not been created yet. Call getDecoderModule() again.
|
|
||||||
setTimeout(function() {
|
|
||||||
THREE.DRACOLoader.getDecoderModule(
|
|
||||||
onDracoDecoderModuleLoadedCallback);
|
|
||||||
}, 10);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
})();
|
/**
|
||||||
|
* 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 ) {
|
||||||
|
var wasmBinary = THREE.DRACOLoader.decoderConfig.wasmBinary;
|
||||||
|
THREE.DRACOLoader.decoderConfig = config || {};
|
||||||
|
THREE.DRACOLoader.releaseDecoderModule();
|
||||||
|
|
||||||
// Releases the DracoDecoderModule instance associated with the draco loader.
|
// Reuse WASM binary.
|
||||||
// The module will be automatically re-created the next time a new geometry is
|
if ( wasmBinary ) THREE.DRACOLoader.decoderConfig.wasmBinary = wasmBinary;
|
||||||
// loaded by THREE.DRACOLoader.
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Releases the singleton DracoDecoderModule instance. Module will be recreated
|
||||||
|
* with the next decoding call.
|
||||||
|
*/
|
||||||
THREE.DRACOLoader.releaseDecoderModule = function () {
|
THREE.DRACOLoader.releaseDecoderModule = function () {
|
||||||
THREE.DRACOLoader.decoderModule = undefined;
|
THREE.DRACOLoader.decoderModulePromise = null;
|
||||||
THREE.DRACOLoader.decoderCreationCalled = false;
|
};
|
||||||
if (THREE.DRACOLoader.dracoDecoderType !== undefined &&
|
|
||||||
THREE.DRACOLoader.dracoDecoderType.wasmBinary !== undefined) {
|
/**
|
||||||
// For WASM build we need to preserve the wasmBinary for future use.
|
* Gets WebAssembly or asm.js singleton instance of DracoDecoderModule
|
||||||
var wasmBinary = THREE.DRACOLoader.dracoDecoderType.wasmBinary;
|
* after testing for browser support. Returns Promise that resolves when
|
||||||
THREE.DRACOLoader.dracoDecoderType = {};
|
* module is available.
|
||||||
THREE.DRACOLoader.dracoDecoderType.wasmBinary = wasmBinary;
|
* @return {Promise<{decoder: DracoDecoderModule}>}
|
||||||
|
*/
|
||||||
|
THREE.DRACOLoader.getDecoderModule = function () {
|
||||||
|
var scope = this;
|
||||||
|
var path = THREE.DRACOLoader.decoderPath;
|
||||||
|
var config = THREE.DRACOLoader.decoderConfig;
|
||||||
|
var promise = THREE.DRACOLoader.decoderModulePromise;
|
||||||
|
|
||||||
|
if ( promise ) return promise;
|
||||||
|
|
||||||
|
// Load source files.
|
||||||
|
if ( typeof DracoDecoderModule !== 'undefined' ) {
|
||||||
|
// Loaded externally.
|
||||||
|
promise = Promise.resolve();
|
||||||
|
} else if ( typeof WebAssembly !== 'object' || config.type === 'js' ) {
|
||||||
|
// Load with asm.js.
|
||||||
|
promise = THREE.DRACOLoader._loadScript( path + 'draco_decoder.js' );
|
||||||
} else {
|
} else {
|
||||||
THREE.DRACOLoader.dracoDecoderType = {};
|
// Load with WebAssembly.
|
||||||
|
config.wasmBinaryFile = path + 'draco_decoder.wasm';
|
||||||
|
promise = THREE.DRACOLoader._loadScript( path + 'draco_wasm_wrapper.js' )
|
||||||
|
.then( function () {
|
||||||
|
return THREE.DRACOLoader._loadArrayBuffer( config.wasmBinaryFile );
|
||||||
|
} )
|
||||||
|
.then( function ( wasmBinary ) {
|
||||||
|
config.wasmBinary = wasmBinary;
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wait for source files, then create and return a decoder.
|
||||||
|
promise = promise.then( function () {
|
||||||
|
return new Promise( function ( resolve ) {
|
||||||
|
config.onModuleLoaded = function ( decoder ) {
|
||||||
|
scope.timeLoaded = performance.now();
|
||||||
|
// Module is Promise-like. Wrap before resolving to avoid loop.
|
||||||
|
resolve( { decoder: decoder } );
|
||||||
|
};
|
||||||
|
DracoDecoderModule( config );
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
THREE.DRACOLoader.decoderModulePromise = promise;
|
||||||
|
return promise;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} src
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
|
THREE.DRACOLoader._loadScript = function ( src ) {
|
||||||
|
var prevScript = document.getElementById( 'decoder_script' );
|
||||||
|
if ( prevScript !== null ) {
|
||||||
|
prevScript.parentNode.removeChild( prevScript );
|
||||||
}
|
}
|
||||||
|
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 );
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} src
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
|
THREE.DRACOLoader._loadArrayBuffer = function ( src ) {
|
||||||
|
var loader = new THREE.FileLoader();
|
||||||
|
loader.setResponseType( 'arraybuffer' );
|
||||||
|
return new Promise( function( resolve, reject ) {
|
||||||
|
loader.load( src, resolve, undefined, reject );
|
||||||
|
});
|
||||||
|
};
|
||||||
|
@ -38,7 +38,23 @@ Include Javascript decoder:
|
|||||||
|
|
||||||
Create DracoLoader by setting the decoder type:
|
Create DracoLoader by setting the decoder type:
|
||||||
~~~~~ js
|
~~~~~ js
|
||||||
var dracoDecoderType = {};
|
// (Optional) Change decoder source directory (defaults to './').
|
||||||
dracoDecoderType.type = 'js';
|
THREE.DRACOLoader.setDecoderPath('./path/to/decoder/');
|
||||||
var dracoLoader = new THREE.DRACOLoader('path_to_decoder', dracoDecoderType);
|
|
||||||
|
// (Optional) Use JS decoder (defaults to WebAssembly if supported).
|
||||||
|
THREE.DRACOLoader.setDecoderConfig({type: 'js'});
|
||||||
|
|
||||||
|
// (Optional) Pre-fetch decoder source files (defaults to load on demand).
|
||||||
|
THREE.DRACOLoader.getDecoderModule();
|
||||||
|
|
||||||
|
var dracoLoader = new THREE.DRACOLoader();
|
||||||
|
|
||||||
|
dracoLoader.load( 'model.drc', function ( geometry ) {
|
||||||
|
|
||||||
|
scene.add( new THREE.Mesh( geometry ) );
|
||||||
|
|
||||||
|
// (Optional) Release the cached decoder module.
|
||||||
|
THREE.DRACOLoader.releaseDecoderModule();
|
||||||
|
|
||||||
|
} );
|
||||||
~~~~~
|
~~~~~
|
||||||
|
@ -44,10 +44,10 @@
|
|||||||
|
|
||||||
var camera, scene, renderer;
|
var camera, scene, renderer;
|
||||||
|
|
||||||
// Global Draco decoder type.
|
// Configure decoder and create loader.
|
||||||
var dracoDecoderType = {};
|
THREE.DRACOLoader.setDecoderPath( '../' );
|
||||||
dracoDecoderType.type = 'js';
|
THREE.DRACOLoader.setDecoderConfig( { type: 'js' } );
|
||||||
var dracoLoader = new THREE.DRACOLoader('../', dracoDecoderType);
|
var dracoLoader = new THREE.DRACOLoader();
|
||||||
|
|
||||||
init();
|
init();
|
||||||
animate();
|
animate();
|
||||||
@ -92,6 +92,9 @@
|
|||||||
mesh.receiveShadow = true;
|
mesh.receiveShadow = true;
|
||||||
scene.add( mesh );
|
scene.add( mesh );
|
||||||
|
|
||||||
|
// Release the cached decoder module.
|
||||||
|
THREE.DRACOLoader.releaseDecoderModule();
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
// renderer
|
// renderer
|
||||||
|
@ -33,14 +33,12 @@
|
|||||||
<script>
|
<script>
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// Global Draco decoder type.
|
// Configure decoder and create loader.
|
||||||
var dracoLoader;
|
THREE.DRACOLoader.setDecoderPath( '../' );
|
||||||
|
var dracoLoader = new THREE.DRACOLoader();
|
||||||
|
|
||||||
createDracoDecoder();
|
// (Optional) Pre-fetch decoder source files.
|
||||||
|
THREE.DRACOLoader.getDecoderModule();
|
||||||
function createDracoDecoder() {
|
|
||||||
dracoLoader = new THREE.DRACOLoader('../');
|
|
||||||
}
|
|
||||||
|
|
||||||
var camera, cameraTarget, scene, renderer;
|
var camera, cameraTarget, scene, renderer;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user