diff --git a/examples/jsm/loaders/TaskManager.js b/examples/jsm/loaders/TaskManager.js index 58dfc62f32d956..6ce03a7cf57e4c 100644 --- a/examples/jsm/loaders/TaskManager.js +++ b/examples/jsm/loaders/TaskManager.js @@ -3,17 +3,27 @@ * @author Kai Salmen / https://kaisalmen.de */ -import { FileLoaderBufferAsync } from "./obj2/utils/FileLoaderBufferAsync.js"; +import { FileLoader } from "../../../build/three.module.js"; /** * */ class TaskManager { - constructor () { + /** + * + * @param {number} [maximumWorkerCount] How many workers are allows. Set 0 for execution on Main ({@link FakeTaskWorker}) + */ + constructor ( maximumWorkerCount ) { this.types = new Map(); this.verbose = false; + this.maximumWorkerCount = 4 + if ( maximumWorkerCount ) { + + this.maximumWorkerCount = maximumWorkerCount; + + } } @@ -30,6 +40,18 @@ class TaskManager { } + /** + * @param {number} maximumWorkerCount How many workers are allows. Set 0 for execution on Main ({@link FakeTaskWorker}) + * @return {TaskManager} + */ + setMaximumWorkerCount ( maximumWorkerCount ) { + + this.maximumWorkerCount = maximumWorkerCount; + return this; + + } + + /** * Returns true if support for the given task type is available. * @param {string} type The type as string @@ -44,16 +66,16 @@ class TaskManager { /** * Registers functionality for a new task type. * @param {string} type The name to be used for registration. - * @param {number} maximumWorkerCount How many workers are allows. Set 0 for execution on Main ({@link FakeTaskWorker}) * @param {function} initFunction The function to be called when the worker is initialised * @param {function} executeFunction The function to be called when the worker is executed * @param {function} comRoutingFunction The function that should handle communication, leave undefined for default behavior + * @param {boolean} fallback Set to true if execution should be performed in main * @param {String[]} [dependencyUrls] * @return {TaskManager} */ - registerType ( type, maximumWorkerCount, initFunction, executeFunction, comRoutingFunction, dependencyUrls ) { + registerType ( type, initFunction, executeFunction, comRoutingFunction, fallback, dependencyUrls ) { - let workerTypeDefinition = new WorkerTypeDefinition( type, maximumWorkerCount, this.verbose ); + let workerTypeDefinition = new WorkerTypeDefinition( type, this.maximumWorkerCount, fallback, this.verbose ); workerTypeDefinition.setFunctions( initFunction, executeFunction, comRoutingFunction ); workerTypeDefinition.setDependencyUrls( dependencyUrls ); this.types.set( type, workerTypeDefinition ); @@ -64,13 +86,12 @@ class TaskManager { /** * Registers functionality for a new task type based on module file. * @param {string} type The name to be used for registration. - * @param {number} maximumWorkerCount How many workers are allows. Set 0 for execution on Main ({@link FakeTaskWorker}) * @param {string} workerJsmUrl The URL to be used for the Worker. Module must provide logic to handle "init" and "execute" messages. * @return {TaskManager} */ - registerTypeJsm ( type, maximumWorkerCount, workerJsmUrl ) { + registerTypeJsm ( type, workerJsmUrl ) { - let workerTypeDefinition = new WorkerTypeDefinition( type, maximumWorkerCount, this.verbose ); + let workerTypeDefinition = new WorkerTypeDefinition( type, this.maximumWorkerCount, false, this.verbose ); workerTypeDefinition.setWorkerJsm( workerJsmUrl ); this.types.set( type, workerTypeDefinition ); return this; @@ -198,14 +219,16 @@ class WorkerTypeDefinition { * * @param {string} type The name of the registered task type. * @param {Number} maximumCount Maximum worker count + * @param {boolean} fallback Set to true if execution should be performed in main * @param {boolean} [verbose] Set if logging should be verbose */ /** */ - constructor ( type, maximumCount, verbose ) { + constructor ( type, maximumCount, fallback, verbose ) { this.type = type; this.maximumCount = maximumCount; + this.fallback = fallback; this.verbose = verbose === true; this.functions = { init: { @@ -259,7 +282,7 @@ class WorkerTypeDefinition { this.functions.execute.ref = executeFunction; this.functions.comRouting.ref = comRoutingFunction; - if ( this.maximumCount > 0 && this.functions.comRouting.ref === undefined || this.functions.comRouting.ref === null ) { + if ( this.fallback && this.functions.comRouting.ref === undefined || this.functions.comRouting.ref === null ) { let comRouting = function ( message, init, execute ) { @@ -324,10 +347,11 @@ class WorkerTypeDefinition { */ async loadDependencies () { - let fileLoaderBufferAsync = new FileLoaderBufferAsync(); + let fileLoader = new FileLoader(); + fileLoader.setResponseType( 'arraybuffer' ); for ( let url of this.functions.dependencies.urls ) { - let dep = await fileLoaderBufferAsync.loadFileAsync( url, report => { if ( this.verbose ) console.log( report.detail.text ); } ) + let dep = await fileLoader.loadAsync( url.href, report => { if ( this.verbose ) console.log( report.detail.text ); } ) this.functions.dependencies.code.push( dep ); } @@ -367,14 +391,18 @@ class WorkerTypeDefinition { async createWorkers ( code ) { let worker, workerBlob; - for ( let i = 0; i < this.maximumCount; i++ ) { + if ( !this.fallback ) { - workerBlob = new Blob( this.functions.dependencies.code.concat( this.workers.code ), { type: 'application/javascript' } ); - worker = new TaskWorker( i, window.URL.createObjectURL( workerBlob ) ); - this.workers.instances[ i ] = worker; + for ( let i = 0; i < this.maximumCount; i ++ ) { + + workerBlob = new Blob( this.functions.dependencies.code.concat( this.workers.code ), { type: 'application/javascript' } ); + worker = new TaskWorker( i, window.URL.createObjectURL( workerBlob ) ); + this.workers.instances[ i ] = worker; + + } } - if ( this.workers.instances.length === 0) { + else { worker = new FakeTaskWorker( 0, this.functions.init.ref, this.functions.execute.ref ); this.workers.instances[ 0 ] = worker; diff --git a/examples/jsm/loaders/obj2/utils/FileLoaderBufferAsync.js b/examples/jsm/loaders/obj2/utils/FileLoaderBufferAsync.js deleted file mode 100644 index 64bdd662035e87..00000000000000 --- a/examples/jsm/loaders/obj2/utils/FileLoaderBufferAsync.js +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @author Kai Salmen / https://kaisalmen.de - * Development repository: https://github.com/kaisalmen/WWOBJLoader - */ - -import { - FileLoader -} from "../../../../../build/three.module.js"; - -/** - * Extension of {@link FileLoader} that configures "arraybuffer" as default response type and carries a specific - * onProgress function for {@link FileLoader#loadAsync}. - */ -class FileLoaderBufferAsync extends FileLoader { - - constructor() { - super(); - this.setResponseType( 'arraybuffer' ); - } - - /** - * Load the resource defined in the first argument. - * - * @param {URL} url - * @param {Function} [onProgress] - * @return {Promise} - */ - loadFileAsync ( url, onProgress ) { - let numericalValueRef = 0; - let numericalValue = 0; - function scopedOnReportProgress( event ) { - - if ( ! event.lengthComputable ) return; - numericalValue = event.loaded / event.total; - if ( numericalValue > numericalValueRef ) { - - numericalValueRef = numericalValue; - let output = 'Download of "' + url + '": ' + ( numericalValue * 100 ).toFixed( 2 ) + '%'; - if ( onProgress !== undefined && onProgress !== null ) { - - onProgress( { - detail: { - type: 'progressLoad', - text: output, - numericalValue: numericalValue - } - } ); - - } - } - } - return this.loadAsync( url.href, scopedOnReportProgress ); - - } - -} - -export { FileLoaderBufferAsync } diff --git a/examples/webgl_loader_taskmanager.html b/examples/webgl_loader_taskmanager.html index 2db15e8c8f3de6..fab479009b5674 100644 --- a/examples/webgl_loader_taskmanager.html +++ b/examples/webgl_loader_taskmanager.html @@ -117,6 +117,7 @@ this.cameraTarget = this.cameraDefaults.posCameraTarget; this.controls = null; + this.maximumWorkerCount = 4; this.taskManager = new TaskManager(); let materialHandler = new MaterialHandler(); @@ -127,10 +128,10 @@ this.meshReceiver = new MeshReceiver( materialHandler ); this.taskNames = new Map (); - this.taskNames.set( 'tmProtoExample', { use: true, quantity: 4 } ); - this.taskNames.set( 'tmProtoExampleJsm', { use: true, quantity: 4 } ); - this.taskNames.set( 'tmProtoExampleJsmNoThree', { use: true, quantity: 4 } ); - this.taskNames.set( 'tmProtoExampleMain', { use: false, quantity: 0 } ); + this.taskNames.set( 'tmProtoExample', { use: true, fallback: false } ); + this.taskNames.set( 'tmProtoExampleJsm', { use: true, fallback: false } ); + this.taskNames.set( 'tmProtoExampleJsmNoThree', { use: true, fallback: false} ); + this.taskNames.set( 'tmProtoExampleMain', { use: false, fallback: true } ); this.tasksToUse = []; this.executions = []; @@ -193,7 +194,7 @@ if ( valueObj.use ) { this.tasksToUse.push( taskName ); - this.taskManager.registerType( taskName, valueObj.quantity, workerInitFunction, workerExecFunction, null, ["../build/three.js"] ); + this.taskManager.registerType( taskName, workerInitFunction, workerExecFunction, null, false, ["../build/three.js"] ); awaiting.push( this.taskManager.initType( taskName, { param1: 'param1value' } ).catch( e => console.error( e ) ) ); } @@ -202,7 +203,7 @@ if ( valueObj.use ) { this.tasksToUse.push( taskName ); - this.taskManager.registerTypeJsm( taskName, valueObj.quantity, './jsm/taskmanager/tmJsmExample.js' ); + this.taskManager.registerTypeJsm( taskName, './jsm/taskmanager/tmJsmExample.js' ); awaiting.push( this.taskManager.initType( taskName, { param1: 'param1value' } ).catch( e => console.error( e ) ) ); } @@ -213,7 +214,7 @@ let torus = new THREE.TorusBufferGeometry( 25, 8, 16, 100 ); let torusPayload = TransferableUtils.packageBufferGeometry( torus, 'torus', 0 ); this.tasksToUse.push( taskName ); - this.taskManager.registerTypeJsm( taskName, valueObj.quantity, './jsm/taskmanager/tmJsmExampleNoThree.js' ); + this.taskManager.registerTypeJsm( taskName, './jsm/taskmanager/tmJsmExampleNoThree.js' ); awaiting.push( this.taskManager.initType( taskName, torusPayload, torusPayload.transferables ).catch( e => console.error( e ) ) ); } @@ -222,7 +223,7 @@ if ( valueObj.use ) { this.tasksToUse.push( taskName ); - this.taskManager.registerType( taskName, valueObj.quantity, workerInitFunction, workerExecFunction, null ); + this.taskManager.registerType( taskName, workerInitFunction, workerExecFunction, null, true ); awaiting.push( this.taskManager.initType( taskName, { param1: 'param1value' } ).catch( e => console.error( e ) ) ); } @@ -380,12 +381,10 @@ let controlStop; let tmControls = { tmProtoExampleName: app.taskNames.get( 'tmProtoExample' ).use, - tmProtoExampleQuantity: app.taskNames.get( 'tmProtoExample' ).quantity, tmProtoExampleJsm: app.taskNames.get( 'tmProtoExampleJsm' ).use, - tmProtoExampleJsmQuantity: app.taskNames.get( 'tmProtoExampleJsm' ).quantity, tmProtoExampleJsmNoThree: app.taskNames.get( 'tmProtoExampleJsmNoThree' ).use, - tmProtoExampleJsmNoThreeQuantity: app.taskNames.get( 'tmProtoExampleJsmNoThree' ).quantity, tmProtoExampleMain: app.taskNames.get( 'tmProtoExampleMain' ).use, + maximumWorkerCount: app.maximumWorkerCount, blockEvent ( event ) { event.stopPropagation(); @@ -421,38 +420,27 @@ } ); menuDiv.appendChild( gui.domElement ); - let folderLegacy = gui.addFolder( 'Worker Legacy + three' ); let taskName0 = 'tmProtoExample'; - controls[ 0 ] = folderLegacy.add( tmControls, taskName0 + 'Name' ).name( 'Use' ); + controls[ 0 ] = gui.add( tmControls, taskName0 + 'Name' ).name( 'Worker Legacy + three' ); controls[ 0 ].onChange( value => { app.taskNames.get( taskName0 ).use = value; } ); - controls[ 1 ] = folderLegacy.add( tmControls, taskName0 + 'Quantity', 1, 16 ).step( 1 ).name( 'Quantity' ); - controls[ 1 ].onChange( value => { app.taskNames.get( taskName0 ).quantity = value; } ); - folderLegacy.open(); - let folderJsmThree = gui.addFolder( 'Worker Jsm + three' ); let taskName1 = 'tmProtoExampleJsm'; - controls[ 2 ] = folderJsmThree.add( tmControls, taskName1 ).name( 'Use' ); - controls[ 2 ].onChange( value => { app.taskNames.get( taskName1 ).use = value; } ); - controls[ 3 ] = folderJsmThree.add( tmControls, taskName1 + 'Quantity', 1, 16 ).step( 1 ).name( 'Quantity' ); - controls[ 3 ].onChange( value => { app.taskNames.get( taskName1 ).quantity = value; } ); - folderJsmThree.open(); + controls[ 1 ] = gui.add( tmControls, taskName1 ).name( 'Worker Jsm + three' ); + controls[ 1 ].onChange( value => { app.taskNames.get( taskName1 ).use = value; } ); - let folderJsmNoThree = gui.addFolder( 'Worker Jsm solo' ); let taskName2 = 'tmProtoExampleJsmNoThree'; - controls[ 4 ] = folderJsmNoThree.add( tmControls, taskName2 ).name( 'Use' ); - controls[ 4 ].onChange( value => { app.taskNames.get( taskName2 ).use = value; } ); - controls[ 5 ] = folderJsmNoThree.add( tmControls, taskName2 + 'Quantity', 1, 16 ).step( 1 ).name( 'Quantity' ); - controls[ 5 ].onChange( value => { app.taskNames.get( taskName2 ).quantity = value; } ); - folderJsmNoThree.open(); + controls[ 2 ] = gui.add( tmControls, taskName2 ).name( 'Worker Jsm solo' ); + controls[ 2 ].onChange( value => { app.taskNames.get( taskName2 ).use = value; } ); - let folderLegacyMain = gui.addFolder( 'Worker Legacy Main' ); let taskName3 = 'tmProtoExampleMain'; - controls[ 6 ] = folderLegacyMain.add( tmControls, taskName3 ).name( 'Use' ); - controls[ 6 ].onChange( value => { app.taskNames.get( taskName3 ).use = value;} ); - folderLegacyMain.open(); + controls[ 3 ] = gui.add( tmControls, taskName3 ).name( 'Worker Legacy Main' ); + controls[ 3 ].onChange( value => { app.taskNames.get( taskName3 ).use = value;} ); - controls[ 7 ] = gui.add( tmControls, 'executeLoading' ).name( 'Engage' ); - controls[ 7 ].domElement.id = 'startButton'; + controls[ 4 ] = gui.add( tmControls, 'maximumWorkerCount', 1, 16 ).step( 1 ).name( 'Maximum worker count' ); + controls[ 4 ].onChange( value => { app.taskManager.setMaximumWorkerCount( value ) } ); + + controls[ 5 ] = gui.add( tmControls, 'executeLoading' ).name( 'Engage' ); + controls[ 5 ].domElement.id = 'startButton'; controlStop = gui.add( tmControls, 'stopExecution' ).name( 'Stop' );