未验证 提交 8916b4cd 编写于 作者: M Mr.doob 提交者: GitHub

Merge pull request #12726 from kaisalmen/OBJLoader2_V220

OBJLoader2 V2.2.0
......@@ -156,10 +156,9 @@
<h2>Methods</h2>
<h3>[method:null validate] ( [page:Function functionCodeBuilder], [page:Boolean forceWorkerReload], Array of [page:String libLocations], [page:String libPath], [page:LoaderSupport.WorkerRunnerRefImpl runnerImpl] )</h3>
<h3>[method:null validate] ( [page:Function functionCodeBuilder], Array of [page:String libLocations], [page:String libPath], [page:LoaderSupport.WorkerRunnerRefImpl runnerImpl] )</h3>
<div>
[page:Function functionCodeBuilder] - Function that is invoked with funcBuildObject and funcBuildSingelton that allows stringification of objects and singletons.<br>
[page:Boolean forceWorkerReload] - Force re-build of the worker code.<br>
Array of [page:String libLocations] - URL of libraries that shall be added to worker code relative to libPath.<br>
[page:String libPath] - Base path used for loading libraries.<br>
[page:LoaderSupport.WorkerRunnerRefImpl runnerImpl] - The default worker parser wrapper implementation (communication and execution). An extended class could be passed here.
......@@ -178,12 +177,6 @@
</div>
<h3>[method:null terminateWorker] ()</h3>
<div>
Terminate the worker and the code.
</div>
<h3>[method:null setCallbacks] ( [page:Function builder], [page:Function onLoad] )</h3>
<div>
[page:Function builder] - The builder function. Default is [page:LoaderSupport.Builder].<br>
......@@ -251,7 +244,7 @@
- prepareWorkers<br>
- enqueueForRun<br>
- processQueue<br>
- deregister
- tearDown
</div>
......@@ -283,7 +276,10 @@
</div>
<h3>[method:null deregister]()</h3>
<h3>[method:null tearDown]( [page:Function callbackOnFinishedProcessing] )</h3>
<div>
[page:Function callbackOnFinishedProcessing] - Function called once all workers finished processing.
</div>
<div>
Terminate all workers.
</div>
......@@ -300,6 +296,11 @@
Returns the maximum number of workers.
</div>
<h3>[method:Boolean isRunning]()</h3>
<div>
Returns if any workers are running.
</div>
<h3>[method:null setCrossOrigin]( [page:String crossOrigin] )</h3>
<div>
......@@ -543,7 +544,7 @@
<h2>Methods</h2>
<h3>[method:null isValid]( [page:Object input] )</h3>
<h3>[method:Boolean isValid]( [page:Object input] )</h3>
<div>
[page:Object input] - Can be anything
</div>
......
......@@ -941,13 +941,8 @@ THREE.LoaderSupport.WorkerRunnerRefImpl = (function () {
* @param {Object} payload Raw mesh description (buffers, params, materials) used to build one to many meshes.
*/
WorkerRunnerRefImpl.prototype.processMessage = function ( payload ) {
var logger = new ConsoleLogger();
if ( Validator.isValid( payload.logger ) ) {
logger.setEnabled( payload.logger.enabled );
logger.setDebug( payload.logger.debug );
}
var logEnabled = payload.logger.enabled;
var logDebug = payload.logger.enabled;
if ( payload.cmd === 'run' ) {
var callbacks = {
......@@ -955,19 +950,20 @@ THREE.LoaderSupport.WorkerRunnerRefImpl = (function () {
self.postMessage( payload );
},
callbackProgress: function ( text ) {
logger.logDebug( 'WorkerRunner: progress: ' + text );
if ( logEnabled && logDebug ) console.debug( 'WorkerRunner: progress: ' + text );
}
};
// Parser is expected to be named as such
var parser = new Parser( logger );
var parser = new Parser();
if ( typeof parser[ 'setLogConfig' ] === 'function' ) parser.setLogConfig( logEnabled, logDebug );
this.applyProperties( parser, payload.params );
this.applyProperties( parser, payload.materials );
this.applyProperties( parser, callbacks );
parser.workerScope = self;
parser.parse( payload.data.input, payload.data.options );
logger.logInfo( 'WorkerRunner: Run complete!' );
if ( logEnabled ) console.log( 'WorkerRunner: Run complete!' );
callbacks.callbackBuilder( {
cmd: 'complete',
......@@ -976,7 +972,7 @@ THREE.LoaderSupport.WorkerRunnerRefImpl = (function () {
} else {
logger.logError( 'WorkerRunner: Received unknown command: ' + payload.cmd );
console.error( 'WorkerRunner: Received unknown command: ' + payload.cmd );
}
};
......@@ -993,170 +989,226 @@ THREE.LoaderSupport.WorkerRunnerRefImpl = (function () {
*/
THREE.LoaderSupport.WorkerSupport = (function () {
var WORKER_SUPPORT_VERSION = '1.1.1';
var WORKER_SUPPORT_VERSION = '2.0.0';
var Validator = THREE.LoaderSupport.Validator;
function WorkerSupport( logger ) {
this.logger = Validator.verifyInput( logger, new THREE.LoaderSupport.ConsoleLogger() );
this.logger.logInfo( 'Using THREE.LoaderSupport.WorkerSupport version: ' + WORKER_SUPPORT_VERSION );
var LoaderWorker = (function () {
// check worker support first
if ( window.Worker === undefined ) throw "This browser does not support web workers!";
if ( window.Blob === undefined ) throw "This browser does not support Blob!";
if ( typeof window.URL.createObjectURL !== 'function' ) throw "This browser does not support Object creation from URL!";
function LoaderWorker( logger ) {
this.logger = Validator.verifyInput( logger, new THREE.LoaderSupport.ConsoleLogger() );
this._reset();
}
LoaderWorker.prototype._reset = function () {
this.worker = null;
this.runnerImplName = null;
this.callbacks = {
builder: null,
onLoad: null
};
this.terminateRequested = false;
this.queuedMessage = null;
this.started = false;
};
LoaderWorker.prototype.initWorker = function ( code, runnerImplName ) {
this.runnerImplName = runnerImplName;
var blob = new Blob( [ code ], { type: 'application/javascript' } );
this.worker = new Worker( window.URL.createObjectURL( blob ) );
this.worker.onmessage = this._receiveWorkerMessage;
this.worker = null;
this.workerCode = null;
this.loading = true;
this.queuedMessage = null;
this.running = false;
this.terminateRequested = false;
// set referemce to this, then processing in worker scope within "_receiveWorkerMessage" can access members
this.worker.runtimeRef = this;
this.callbacks = {
builder: null,
onLoad: null
// process stored queuedMessage
this._postMessage();
};
}
/**
* Validate the status of worker code and the derived worker.
* @memberOf THREE.LoaderSupport.WorkerSupport
*
* @param {Function} functionCodeBuilder Function that is invoked with funcBuildObject and funcBuildSingelton that allows stringification of objects and singletons.
* @param {boolean} forceWorkerReload Force re-build of the worker code.
* @param {String[]} libLocations URL of libraries that shall be added to worker code relative to libPath
* @param {String} libPath Base path used for loading libraries
* @param {THREE.LoaderSupport.WorkerRunnerRefImpl} runnerImpl The default worker parser wrapper implementation (communication and execution). An extended class could be passed here.
*/
WorkerSupport.prototype.validate = function ( functionCodeBuilder, forceWorkerReload, libLocations, libPath, runnerImpl ) {
this.running = false;
if ( forceWorkerReload ) {
/**
* Executed in worker scope
*/
LoaderWorker.prototype._receiveWorkerMessage = function ( e ) {
var payload = e.data;
switch ( payload.cmd ) {
case 'meshData':
case 'materialData':
case 'imageData':
this.runtimeRef.callbacks.builder( payload );
break;
this.worker = null;
this.workerCode = null;
this.loading = true;
this.queuedMessage = null;
this.callbacks.builder = null;
this.callbacks.onLoad = null;
case 'complete':
this.runtimeRef.queuedMessage = null;
this.started = false;
this.runtimeRef.callbacks.onLoad( payload.msg );
}
if ( this.runtimeRef.terminateRequested ) {
this.runtimeRef.logger.logInfo( 'WorkerSupport [' + this.runtimeRef.runnerImplName + ']: Run is complete. Terminating application on request!' );
this.runtimeRef._terminate();
}
break;
case 'error':
this.runtimeRef.logger.logError( 'WorkerSupport [' + this.runtimeRef.runnerImplName + ']: Reported error: ' + payload.msg );
this.runtimeRef.queuedMessage = null;
this.started = false;
this.runtimeRef.callbacks.onLoad( payload.msg );
if ( ! Validator.isValid( this.worker ) ) {
if ( this.runtimeRef.terminateRequested ) {
this.logger.logInfo( 'WorkerSupport: Building worker code...' );
this.logger.logTimeStart( 'buildWebWorkerCode' );
this.runtimeRef.logger.logInfo( 'WorkerSupport [' + this.runtimeRef.runnerImplName + ']: Run reported error. Terminating application on request!' );
this.runtimeRef._terminate();
var workerRunner;
if ( Validator.isValid( runnerImpl ) ) {
}
break;
this.logger.logInfo( 'WorkerSupport: Using "' + runnerImpl.name + '" as Runncer class for worker.' );
workerRunner = runnerImpl;
default:
this.runtimeRef.logger.logError( 'WorkerSupport [' + this.runtimeRef.runnerImplName + ']: Received unknown command: ' + payload.cmd );
break;
}
};
LoaderWorker.prototype.setCallbacks = function ( builder, onLoad ) {
this.callbacks.builder = Validator.verifyInput( builder, this.callbacks.builder );
this.callbacks.onLoad = Validator.verifyInput( onLoad, this.callbacks.onLoad );
};
LoaderWorker.prototype.run = function( payload ) {
if ( Validator.isValid( this.queuedMessage ) ) {
console.warn( 'Already processing message. Rejecting new run instruction' );
return;
} else {
this.logger.logInfo( 'WorkerSupport: Using DEFAULT "THREE.LoaderSupport.WorkerRunnerRefImpl" as Runncer class for worker.' );
workerRunner = THREE.LoaderSupport.WorkerRunnerRefImpl;
this.queuedMessage = payload;
this.started = true;
}
if ( ! Validator.isValid( this.callbacks.builder ) ) throw 'Unable to run as no "builder" callback is set.';
if ( ! Validator.isValid( this.callbacks.onLoad ) ) throw 'Unable to run as no "onLoad" callback is set.';
if ( payload.cmd !== 'run' ) payload.cmd = 'run';
if ( Validator.isValid( payload.logger ) ) {
var scope = this;
var buildWorkerCode = function ( baseWorkerCode ) {
scope.workerCode = baseWorkerCode;
if ( workerRunner == THREE.LoaderSupport.WorkerRunnerRefImpl ) {
payload.logger.enabled = Validator.verifyInput( payload.logger.enabled, true );
payload.logger.debug = Validator.verifyInput( payload.logger.debug, false );
scope.workerCode += buildObject( 'Validator', THREE.LoaderSupport.Validator );
scope.workerCode += buildSingelton( 'ConsoleLogger', 'ConsoleLogger', THREE.LoaderSupport.ConsoleLogger );
} else {
payload.logger = {
enabled: true,
debug: false
}
scope.workerCode += functionCodeBuilder( buildObject, buildSingelton );
scope.workerCode += buildSingelton( workerRunner.name, workerRunner.name, workerRunner );
scope.workerCode += 'new ' + workerRunner.name + '();\n\n';
var blob = new Blob( [ scope.workerCode ], { type: 'application/javascript' } );
scope.worker = new Worker( window.URL.createObjectURL( blob ) );
scope.logger.logTimeEnd( 'buildWebWorkerCode' );
}
this._postMessage();
};
var receiveWorkerMessage = function ( e ) {
var payload = e.data;
LoaderWorker.prototype._postMessage = function () {
if ( Validator.isValid( this.queuedMessage ) && Validator.isValid( this.worker ) ) {
switch ( payload.cmd ) {
case 'meshData':
case 'materialData':
case 'imageData':
scope.callbacks.builder( payload );
break;
this.worker.postMessage( this.queuedMessage );
case 'complete':
scope.callbacks.onLoad( payload.msg );
scope.running = false;
}
};
if ( scope.terminateRequested ) {
LoaderWorker.prototype.setTerminateRequested = function ( terminateRequested ) {
this.terminateRequested = terminateRequested === true;
if ( this.terminateRequested && Validator.isValid( this.worker ) && ! Validator.isValid( this.queuedMessage ) && this.started ) {
scope.logger.logInfo( 'WorkerSupport [' + workerRunner + ']: Run is complete. Terminating application on request!' );
scope.terminateWorker();
this.logger.logInfo( 'Worker is terminated immediately as it is not running!' );
this._terminate();
}
break;
}
};
case 'error':
scope.logger.logError( 'WorkerSupport [' + workerRunner + ']: Reported error: ' + payload.msg );
break;
LoaderWorker.prototype._terminate = function () {
this.worker.terminate();
this._reset();
};
default:
scope.logger.logError( 'WorkerSupport [' + workerRunner + ']: Received unknown command: ' + payload.cmd );
break;
return LoaderWorker;
}
};
scope.worker.addEventListener( 'message', receiveWorkerMessage, false );
scope.loading = false;
scope._postMessage();
};
})();
if ( Validator.isValid( libLocations ) && libLocations.length > 0 ) {
function WorkerSupport( logger ) {
this.logger = Validator.verifyInput( logger, new THREE.LoaderSupport.ConsoleLogger() );
this.logger.logInfo( 'Using THREE.LoaderSupport.WorkerSupport version: ' + WORKER_SUPPORT_VERSION );
var libsContent = '';
var loadAllLibraries = function ( path, locations ) {
if ( locations.length === 0 ) {
// check worker support first
if ( window.Worker === undefined ) throw "This browser does not support web workers!";
if ( window.Blob === undefined ) throw "This browser does not support Blob!";
if ( typeof window.URL.createObjectURL !== 'function' ) throw "This browser does not support Object creation from URL!";
buildWorkerCode( libsContent );
this.loaderWorker = new LoaderWorker( this.logger );
}
} else {
/**
* Validate the status of worker code and the derived worker.
* @memberOf THREE.LoaderSupport.WorkerSupport
*
* @param {Function} functionCodeBuilder Function that is invoked with funcBuildObject and funcBuildSingelton that allows stringification of objects and singletons.
* @param {String[]} libLocations URL of libraries that shall be added to worker code relative to libPath
* @param {String} libPath Base path used for loading libraries
* @param {THREE.LoaderSupport.WorkerRunnerRefImpl} runnerImpl The default worker parser wrapper implementation (communication and execution). An extended class could be passed here.
*/
WorkerSupport.prototype.validate = function ( functionCodeBuilder, libLocations, libPath, runnerImpl ) {
if ( Validator.isValid( this.loaderWorker.worker ) ) return;
var loadedLib = function ( contentAsString ) {
libsContent += contentAsString;
loadAllLibraries( path, locations );
};
this.logger.logInfo( 'WorkerSupport: Building worker code...' );
this.logger.logTimeStart( 'buildWebWorkerCode' );
var fileLoader = new THREE.FileLoader();
fileLoader.setPath( path );
fileLoader.setResponseType( 'text' );
fileLoader.load( locations[ 0 ], loadedLib );
locations.shift();
if ( Validator.isValid( runnerImpl ) ) {
}
};
loadAllLibraries( libPath, libLocations );
this.logger.logInfo( 'WorkerSupport: Using "' + runnerImpl.name + '" as Runncer class for worker.' );
} else {
} else {
buildWorkerCode( '' );
runnerImpl = THREE.LoaderSupport.WorkerRunnerRefImpl;
this.logger.logInfo( 'WorkerSupport: Using DEFAULT "THREE.LoaderSupport.WorkerRunnerRefImpl" as Runncer class for worker.' );
}
}
};
/**
* Terminate the worker and the code.
* @memberOf THREE.LoaderSupport.WorkerSupport
*/
WorkerSupport.prototype.terminateWorker = function () {
if ( Validator.isValid( this.worker ) ) {
this.worker.terminate();
var userWorkerCode = functionCodeBuilder( buildObject, buildSingelton );
userWorkerCode += buildSingelton( runnerImpl.name, runnerImpl.name, runnerImpl );
userWorkerCode += 'new ' + runnerImpl.name + '();\n\n';
var scope = this;
if ( Validator.isValid( libLocations ) && libLocations.length > 0 ) {
var libsContent = '';
var loadAllLibraries = function ( path, locations ) {
if ( locations.length === 0 ) {
scope.loaderWorker.initWorker( libsContent + userWorkerCode, scope.logger, runnerImpl.name );
scope.logger.logTimeEnd( 'buildWebWorkerCode' );
} else {
var loadedLib = function ( contentAsString ) {
libsContent += contentAsString;
loadAllLibraries( path, locations );
};
var fileLoader = new THREE.FileLoader();
fileLoader.setPath( path );
fileLoader.setResponseType( 'text' );
fileLoader.load( locations[ 0 ], loadedLib );
locations.shift();
}
};
loadAllLibraries( libPath, libLocations );
} else {
this.loaderWorker.initWorker( userWorkerCode, this.logger, runnerImpl.name );
this.logger.logTimeEnd( 'buildWebWorkerCode' );
}
this.worker = null;
this.workerCode = null;
};
/**
......@@ -1167,10 +1219,27 @@ THREE.LoaderSupport.WorkerSupport = (function () {
* @param {Function} onLoad The function that is called when parsing is complete.
*/
WorkerSupport.prototype.setCallbacks = function ( builder, onLoad ) {
this.callbacks = {
builder: builder,
onLoad: onLoad
};
this.loaderWorker.setCallbacks( builder, onLoad );
};
/**
* Runs the parser with the provided configuration.
* @memberOf THREE.LoaderSupport.WorkerSupport
*
* @param {Object} payload Raw mesh description (buffers, params, materials) used to build one to many meshes.
*/
WorkerSupport.prototype.run = function ( payload ) {
this.loaderWorker.run( payload );
};
/**
* Request termination of worker once parser is finished.
* @memberOf THREE.LoaderSupport.WorkerSupport
*
* @param {boolean} terminateRequested True or false.
*/
WorkerSupport.prototype.setTerminateRequested = function ( terminateRequested ) {
this.loaderWorker.setTerminateRequested( terminateRequested );
};
var buildObject = function ( fullName, object ) {
......@@ -1229,41 +1298,8 @@ THREE.LoaderSupport.WorkerSupport = (function () {
return objectString;
};
/**
* Request termination of worker once parser is finished.
* @memberOf THREE.LoaderSupport.WorkerSupport
*
* @param {boolean} terminateRequested True or false.
*/
WorkerSupport.prototype.setTerminateRequested = function ( terminateRequested ) {
this.terminateRequested = terminateRequested === true;
};
/**
* Runs the parser with the provided configuration.
* @memberOf THREE.LoaderSupport.WorkerSupport
*
* @param {Object} payload Raw mesh description (buffers, params, materials) used to build one to many meshes.
*/
WorkerSupport.prototype.run = function ( payload ) {
if ( ! Validator.isValid( this.callbacks.builder ) ) throw 'Unable to run as no "builder" callback is set.';
if ( ! Validator.isValid( this.callbacks.onLoad ) ) throw 'Unable to run as no "onLoad" callback is set.';
if ( Validator.isValid( this.worker ) || this.loading ) {
if ( payload.cmd !== 'run' ) payload.cmd = 'run';
this.queuedMessage = payload;
this.running = true;
this._postMessage();
}
};
WorkerSupport.prototype._postMessage = function () {
if ( ! this.loading && Validator.isValid( this.queuedMessage ) ) {
this.worker.postMessage( this.queuedMessage );
}
};
return WorkerSupport;
})();
/**
......@@ -1272,7 +1308,7 @@ THREE.LoaderSupport.WorkerSupport = (function () {
* prepareWorkers
* enqueueForRun
* processQueue
* deregister
* tearDown (to force stop)
*
* @class
*
......@@ -1281,7 +1317,7 @@ THREE.LoaderSupport.WorkerSupport = (function () {
*/
THREE.LoaderSupport.WorkerDirector = (function () {
var LOADER_WORKER_DIRECTOR_VERSION = '2.0.0';
var LOADER_WORKER_DIRECTOR_VERSION = '2.1.0';
var Validator = THREE.LoaderSupport.Validator;
......@@ -1301,10 +1337,13 @@ THREE.LoaderSupport.WorkerDirector = (function () {
this.workerDescription = {
classDef: classDef,
globalCallbacks: {},
workerSupports: []
workerSupports: {}
};
this.objectsCompleted = 0;
this.instructionQueue = [];
this.instructionQueuePointer = 0;
this.callbackOnFinishedProcessing = null;
}
/**
......@@ -1349,30 +1388,21 @@ THREE.LoaderSupport.WorkerDirector = (function () {
if ( Validator.isValid( globalCallbacks ) ) this.workerDescription.globalCallbacks = globalCallbacks;
this.maxQueueSize = Math.min( maxQueueSize, MAX_QUEUE_SIZE );
this.maxWebWorkers = Math.min( maxWebWorkers, MAX_WEB_WORKER );
this.maxWebWorkers = Math.min( this.maxWebWorkers, this.maxQueueSize );
this.objectsCompleted = 0;
this.instructionQueue = [];
this.instructionQueuePointer = 0;
var start = this.workerDescription.workerSupports.length;
var i;
if ( start < this.maxWebWorkers ) {
for ( i = start; i < this.maxWebWorkers; i++ ) {
this.workerDescription.workerSupports[ i ] = {
workerSupport: new THREE.LoaderSupport.WorkerSupport( this.logger ),
loader: null
};
}
} else {
for ( var instanceNo = 0; instanceNo < this.maxWebWorkers; instanceNo++ ) {
for ( i = start - 1; i >= this.maxWebWorkers; i-- ) {
this.workerDescription.workerSupports[ instanceNo ] = {
instanceNo: instanceNo,
inUse: false,
terminateRequested: false,
workerSupport: new THREE.LoaderSupport.WorkerSupport( this.logger ),
loader: null
};
this.workerDescription.workerSupports[ i ].workerSupport.setRequestTerminate( true );
this.workerDescription.workerSupports.pop();
}
}
};
......@@ -1388,47 +1418,68 @@ THREE.LoaderSupport.WorkerDirector = (function () {
}
};
/**
* Returns if any workers are running.
*
* @memberOf THREE.LoaderSupport.WorkerDirector
* @returns {boolean}
*/
WorkerDirector.prototype.isRunning = function () {
var wsKeys = Object.keys( this.workerDescription.workerSupports );
return ( ( this.instructionQueue.length > 0 && this.instructionQueuePointer < this.instructionQueue.length ) || wsKeys.length > 0 );
};
/**
* Process the instructionQueue until it is depleted.
* @memberOf THREE.LoaderSupport.WorkerDirector
*/
WorkerDirector.prototype.processQueue = function () {
if ( this.instructionQueue.length === 0 ) return;
var prepData, supportDesc;
for ( var instanceNo in this.workerDescription.workerSupports ) {
var length = Math.min( this.maxWebWorkers, this.instructionQueue.length );
for ( var i = 0; i < length; i++ ) {
supportDesc = this.workerDescription.workerSupports[ instanceNo ];
if ( ! supportDesc.inUse ) {
this._kickWorkerRun( this.instructionQueue[ 0 ], i );
this.instructionQueue.shift();
if ( this.instructionQueuePointer < this.instructionQueue.length ) {
}
};
prepData = this.instructionQueue[ this.instructionQueuePointer ];
this._kickWorkerRun( prepData, supportDesc );
this.instructionQueuePointer++;
WorkerDirector.prototype._kickWorkerRun = function( prepData, workerInstanceNo ) {
var scope = this;
var directorOnLoad = function ( event ) {
scope.objectsCompleted++;
} else {
var nextPrepData = scope.instructionQueue[ 0 ];
if ( Validator.isValid( nextPrepData ) ) {
this._deregister( supportDesc );
scope.instructionQueue.shift();
scope.logger.logInfo( '\nAssigning next item from queue to worker (queue length: ' + scope.instructionQueue.length + ')\n\n' );
scope._kickWorkerRun( nextPrepData, event.detail.instanceNo );
}
} else if ( scope.instructionQueue.length === 0 ) {
}
scope.deregister();
}
}
};
if ( ! this.isRunning() && this.callbackOnFinishedProcessing !== null ) {
this.callbackOnFinishedProcessing();
this.callbackOnFinishedProcessing = null;
}
};
WorkerDirector.prototype._kickWorkerRun = function( prepData, supportDesc ) {
supportDesc.inUse = true;
supportDesc.workerSupport.setTerminateRequested( supportDesc.terminateRequested );
this.logger.logInfo( '\nAssigning next item from queue to worker (queue length: ' + this.instructionQueue.length + ')\n\n' );
var scope = this;
var prepDataCallbacks = prepData.getCallbacks();
var globalCallbacks = this.workerDescription.globalCallbacks;
var wrapperOnLoad = function ( event ) {
if ( Validator.isValid( globalCallbacks.onLoad ) ) globalCallbacks.onLoad( event );
if ( Validator.isValid( prepDataCallbacks.onLoad ) ) prepDataCallbacks.onLoad( event );
directorOnLoad( event );
scope.objectsCompleted++;
supportDesc.inUse = false;
scope.processQueue();
};
var wrapperOnProgress = function ( event ) {
......@@ -1441,8 +1492,7 @@ THREE.LoaderSupport.WorkerDirector = (function () {
if ( Validator.isValid( prepDataCallbacks.onMeshAlter ) ) prepDataCallbacks.onMeshAlter( event );
};
var supportTuple = this.workerDescription.workerSupports[ workerInstanceNo ];
supportTuple.loader = this._buildLoader( workerInstanceNo );
supportDesc.loader = this._buildLoader( supportDesc.instanceNo );
var updatedCallbacks = new THREE.LoaderSupport.Callbacks();
updatedCallbacks.setCallbackOnLoad( wrapperOnLoad );
......@@ -1450,13 +1500,13 @@ THREE.LoaderSupport.WorkerDirector = (function () {
updatedCallbacks.setCallbackOnMeshAlter( wrapperOnMeshAlter );
prepData.callbacks = updatedCallbacks;
supportTuple.loader.run( prepData, supportTuple.workerSupport );
supportDesc.loader.run( prepData, supportDesc.workerSupport );
};
WorkerDirector.prototype._buildLoader = function ( instanceNo ) {
var classDef = this.workerDescription.classDef;
var loader = Object.create( classDef.prototype );
this.workerDescription.classDef.call( loader, null, this.logger );
this.workerDescription.classDef.call( loader, THREE.DefaultLoadingManager, this.logger );
// verify that all required functions are implemented
if ( ! loader.hasOwnProperty( 'instanceNo' ) ) throw classDef.name + ' has no property "instanceNo".';
......@@ -1466,36 +1516,47 @@ THREE.LoaderSupport.WorkerDirector = (function () {
throw classDef.name + ' has no property "workerSupport".';
} else if ( ! classDef.workerSupport instanceof THREE.LoaderSupport.WorkerSupport ) {
throw classDef.name + '.workerSupport is not of type "THREE.LoaderSupport.WorkerSupport".';
}
if ( typeof loader.run !== 'function' ) throw classDef.name + ' has no function "run".';
if ( ! loader.hasOwnProperty( 'callbacks' ) || ! Validator.isValid( loader.callbacks ) ) {
this.logger.logWarn( classDef.name + ' has an invalid property "callbacks". Will change to "THREE.LoaderSupport.Callbacks"' );
loader.callbacks = new THREE.LoaderSupport.Callbacks();
}
return loader;
};
WorkerDirector.prototype._deregister = function ( supportDesc ) {
if ( Validator.isValid( supportDesc ) ) {
supportDesc.workerSupport.setTerminateRequested( true );
this.logger.logInfo( 'Requested termination of worker #' + supportDesc.instanceNo + '.' );
var loaderCallbacks = supportDesc.loader.callbacks;
if ( Validator.isValid( loaderCallbacks.onProgress ) ) loaderCallbacks.onProgress( { detail: { text: '' } } );
delete this.workerDescription.workerSupports[ supportDesc.instanceNo ];
}
};
/**
* Terminate all workers.
* @memberOf THREE.LoaderSupport.WorkerDirector
*
* @param {callback} callbackOnFinishedProcessing Function called once all workers finished processing.
*/
WorkerDirector.prototype.deregister = function () {
WorkerDirector.prototype.tearDown = function ( callbackOnFinishedProcessing ) {
this.logger.logInfo( 'WorkerDirector received the deregister call. Terminating all workers!' );
for ( var i = 0, length = this.workerDescription.workerSupports.length; i < length; i++ ) {
this.instructionQueuePointer = this.instructionQueue.length;
this.callbackOnFinishedProcessing = Validator.verifyInput( callbackOnFinishedProcessing, null );
var supportTuple = this.workerDescription.workerSupports[ i ];
supportTuple.workerSupport.setTerminateRequested( true );
this.logger.logInfo( 'Requested termination of worker.' );
for ( var name in this.workerDescription.workerSupports ) {
var loaderCallbacks = supportTuple.loader.callbacks;
if ( Validator.isValid( loaderCallbacks.onProgress ) ) loaderCallbacks.onProgress( { detail: { text: '' } } );
this.workerDescription.workerSupports[ name ].terminateRequested = true;
}
this.workerDescription.workerSupports = [];
this.instructionQueue = [];
};
return WorkerDirector;
......
......@@ -7,6 +7,8 @@
if ( THREE.OBJLoader2 === undefined ) { THREE.OBJLoader2 = {} }
if ( THREE.LoaderSupport === undefined ) console.error( '"THREE.LoaderSupport" is not available. "THREE.OBJLoader2" requires it. Please include "LoaderSupport.js" in your HTML.' );
/**
* Use this class to load OBJ data from files or to parse OBJ data from an arraybuffer
* @class
......@@ -16,9 +18,10 @@ if ( THREE.OBJLoader2 === undefined ) { THREE.OBJLoader2 = {} }
*/
THREE.OBJLoader2 = (function () {
var OBJLOADER2_VERSION = '2.1.2';
var OBJLOADER2_VERSION = '2.2.0';
var LoaderBase = THREE.LoaderSupport.LoaderBase;
var Validator = THREE.LoaderSupport.Validator;
var ConsoleLogger = THREE.LoaderSupport.ConsoleLogger;
OBJLoader2.prototype = Object.create( THREE.LoaderSupport.LoaderBase.prototype );
OBJLoader2.prototype.constructor = OBJLoader2;
......@@ -126,10 +129,6 @@ THREE.OBJLoader2 = (function () {
this.workerSupport = workerSupportExternal;
this.logger = workerSupportExternal.logger;
} else {
this.terminateWorkerOnLoad = true;
}
var scope = this;
var onMaterialsLoaded = function ( materials ) {
......@@ -176,7 +175,8 @@ THREE.OBJLoader2 = (function () {
OBJLoader2.prototype.parse = function ( content ) {
this.logger.logTimeStart( 'OBJLoader2 parse: ' + this.modelName );
var parser = new Parser( this.logger );
var parser = new Parser();
parser.setLogConfig( this.logger.enabled, this.logger.debug );
parser.setMaterialPerSmoothingGroup( this.materialPerSmoothingGroup );
parser.setUseIndices( this.useIndices );
parser.setDisregardNormals( this.disregardNormals );
......@@ -239,7 +239,6 @@ THREE.OBJLoader2 = (function () {
}
}
);
if ( scope.terminateWorkerOnLoad ) scope.workerSupport.terminateWorker();
scope.logger.logTimeEnd( 'OBJLoader2 parseAsync: ' + scope.modelName );
};
var scopedOnMeshLoaded = function ( payload ) {
......@@ -257,6 +256,8 @@ THREE.OBJLoader2 = (function () {
workerCode += '/**\n';
workerCode += ' * This code was constructed by OBJLoader2 buildCode.\n';
workerCode += ' */\n\n';
workerCode += funcBuildObject( 'Validator', Validator );
workerCode += funcBuildSingelton( 'ConsoleLogger', 'ConsoleLogger', ConsoleLogger );
workerCode += funcBuildSingelton( 'LoaderBase', 'LoaderBase', LoaderBase );
workerCode += funcBuildObject( 'Consts', Consts );
workerCode += funcBuildSingelton( 'Parser', 'Parser', Parser );
......@@ -267,6 +268,7 @@ THREE.OBJLoader2 = (function () {
};
this.workerSupport.validate( buildCode, false );
this.workerSupport.setCallbacks( scopedOnMeshLoaded, scopedOnLoad );
if ( scope.terminateWorkerOnLoad ) this.workerSupport.setTerminateRequested( true );
var materialNames = {};
var materials = this.builder.getMaterials();
......@@ -330,7 +332,9 @@ THREE.OBJLoader2 = (function () {
*/
var Parser = (function () {
function Parser( logger ) {
var ConsoleLogger = THREE.LoaderSupport.ConsoleLogger;
function Parser() {
this.callbackProgress = null;
this.callbackBuilder = null;
......@@ -348,7 +352,7 @@ THREE.OBJLoader2 = (function () {
faces: 0,
doubleIndicesCount: 0
};
this.logger = logger;
this.logger = new ConsoleLogger();
this.totalBytes = 0;
this.reachedFaces = false;
};
......@@ -383,6 +387,11 @@ THREE.OBJLoader2 = (function () {
this.callbackProgress = callbackProgress;
};
Parser.prototype.setLogConfig = function ( enabled, debug ) {
this.logger.setEnabled( enabled );
this.logger.setDebug( debug );
};
Parser.prototype.configure = function () {
this.rawMesh = new RawMesh( this.materialPerSmoothingGroup, this.useIndices, this.disregardNormals );
......@@ -1359,6 +1368,7 @@ THREE.OBJLoader2 = (function () {
* @param {string} [crossOrigin] CORS value
*/
OBJLoader2.prototype._loadMtl = function ( resource, callbackOnLoad, crossOrigin ) {
if ( THREE.MTLLoader === undefined ) console.error( '"THREE.MTLLoader" is not available. "THREE.OBJLoader2" requires it for loading MTL files.' );
if ( Validator.isValid( resource ) ) this.logger.logTimeStart( 'Loading MTL: ' + resource.name );
var materials = [];
......
......@@ -142,12 +142,14 @@
workerCode += '/**\n';
workerCode += ' * This code was constructed by MeshSpray buildCode.\n';
workerCode += ' */\n\n';
workerCode += funcBuildObject( 'Validator', Validator );
workerCode += funcBuildSingelton( 'ConsoleLogger', 'ConsoleLogger', ConsoleLogger );
workerCode += funcBuildSingelton( 'Parser', 'Parser', Parser );
return workerCode;
};
var libs2Load = [ 'build/three.min.js' ];
this.workerSupport.validate( buildCode, false, libs2Load, '../' );
this.workerSupport.validate( buildCode, libs2Load, '../' );
this.workerSupport.setCallbacks( scopeBuilderFunc, scopeFuncComplete );
this.workerSupport.run(
{
......@@ -173,7 +175,9 @@
var Parser = ( function () {
function Parser( logger ) {
var ConsoleLogger = THREE.LoaderSupport.ConsoleLogger;
function Parser() {
this.sizeFactor = 0.5;
this.localOffsetFactor = 1.0;
this.globalObjectCount = 0;
......@@ -181,10 +185,16 @@
this.dimension = 200;
this.quantity = 1;
this.callbackBuilder = null;
this.logger = logger;
this.callbackProgress = null;
this.logger = new ConsoleLogger();
this.serializedMaterials = null;
};
Parser.prototype.setLogConfig = function ( enabled, debug ) {
this.logger.setEnabled( enabled );
this.logger.setDebug( debug );
};
Parser.prototype.parse = function () {
var baseTriangle = [ 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 0.0, -1.0, 1.0 ];
var vertices = [];
......@@ -389,12 +399,11 @@
var maxWebWorkers = 4;
var radius = 640;
var logger = new THREE.LoaderSupport.ConsoleLogger( false );
this.workerDirector = new THREE.LoaderSupport.WorkerDirector( MeshSpray, logger );
this.workerDirector.setCrossOrigin( 'anonymous' );
var workerDirector = new THREE.LoaderSupport.WorkerDirector( MeshSpray, logger );
workerDirector.setCrossOrigin( 'anonymous' );
var scope = this;
var callbackOnLoad = function ( event ) {
logger.logInfo( 'Worker #' + event.detail.instanceNo + ': Completed loading. (#' + scope.workerDirector.objectsCompleted + ')' );
logger.logInfo( 'Worker #' + event.detail.instanceNo + ': Completed loading. (#' + workerDirector.objectsCompleted + ')' );
};
var reportProgress = function( event ) {
document.getElementById( 'feedback' ).innerHTML = event.detail.text;
......@@ -416,7 +425,7 @@
callbacks.setCallbackOnMeshAlter( callbackMeshAlter );
callbacks.setCallbackOnLoad( callbackOnLoad );
callbacks.setCallbackOnProgress( reportProgress );
this.workerDirector.prepareWorkers( callbacks, maxQueueSize, maxWebWorkers );
workerDirector.prepareWorkers( callbacks, maxQueueSize, maxWebWorkers );
var prepData;
var pivot;
......@@ -440,9 +449,9 @@
prepData.dimension = Math.max( Math.random() * 500, 100 );
prepData.globalObjectCount = globalObjectCount++;
this.workerDirector.enqueueForRun( prepData );
workerDirector.enqueueForRun( prepData );
}
this.workerDirector.processQueue();
workerDirector.processQueue();
};
MeshSprayApp.prototype.resizeDisplayGL = function () {
......
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - WWOBJLoader2</title>
<title>three.js webgl - OBJLoader2 usage options</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
......@@ -243,6 +243,8 @@
var scope = this;
var objLoader = new THREE.OBJLoader2();
var callbackOnLoad = function ( event ) {
objLoader.workerSupport.setTerminateRequested( true );
var local = new THREE.Object3D();
local.name = 'Pivot_WaltHead';
local.position.set( -125, 50, 0 );
......@@ -257,6 +259,7 @@
var onLoadMtl = function ( materials ) {
objLoader.setModelName( modelName );
objLoader.setMaterials( materials );
objLoader.terminateWorkerOnLoad = false;
objLoader.load( 'obj/walt/WaltHead.obj', callbackOnLoad, null, null, null, true );
};
objLoader.loadMtl( 'obj/walt//WaltHead.mtl', 'WaltHead.mtl', null, onLoadMtl );
......
......@@ -113,7 +113,7 @@
this.logger = new THREE.LoaderSupport.ConsoleLogger();
this.logger.setEnabled( false );
this.workerDirector = new THREE.LoaderSupport.WorkerDirector( THREE.OBJLoader2, this.logger );
this.workerDirector = new THREE.LoaderSupport.WorkerDirector( THREE.OBJLoader2, this.logger );
this.workerDirector.setCrossOrigin( 'anonymous' );
this.controls = null;
......@@ -380,7 +380,24 @@
};
WWParallels.prototype.terminateManager = function () {
this.workerDirector.deregister();
this.workerDirector.tearDown();
this.running = false;
};
WWParallels.prototype.terminateManagerAndClearScene = function () {
var scope = this;
var scopedClearAllAssests = function (){
scope.clearAllAssests();
};
if ( this.workerDirector.isRunning() ) {
this.workerDirector.tearDown( scopedClearAllAssests );
} else {
scopedClearAllAssests();
}
this.running = false;
};
......@@ -402,8 +419,7 @@
app.terminateManager();
},
clearAllAssests: function () {
app.terminateManager();
app.clearAllAssests();
app.terminateManagerAndClearScene();
}
};
var gui = new dat.GUI( {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册