diff --git a/examples/jsm/loaders/OBJLoader2.d.ts b/examples/jsm/loaders/OBJLoader2.d.ts index bef4fdb94d536494943486447fb656a6a47b9281..e0b66095f59ff887cebdad8185913daac3c3807f 100644 --- a/examples/jsm/loaders/OBJLoader2.d.ts +++ b/examples/jsm/loaders/OBJLoader2.d.ts @@ -4,7 +4,7 @@ import { Object3D, } from '../../../src/Three'; -import { OBJLoader2Parser } from './obj2/worker/parallel/OBJLoader2Parser'; +import { OBJLoader2Parser } from './obj2/OBJLoader2Parser'; import { MaterialHandler } from './obj2/shared/MaterialHandler'; import { MeshReceiver } from './obj2/shared/MeshReceiver'; diff --git a/examples/jsm/loaders/OBJLoader2.js b/examples/jsm/loaders/OBJLoader2.js index a9bf83a87610f042fbd746cab325cc61bff4377a..3ba72076acc2ff2e359dc91460c873c22263c9a7 100644 --- a/examples/jsm/loaders/OBJLoader2.js +++ b/examples/jsm/loaders/OBJLoader2.js @@ -9,7 +9,7 @@ import { Loader } from "../../../build/three.module.js"; -import { OBJLoader2Parser } from "./obj2/worker/parallel/OBJLoader2Parser.js"; +import { OBJLoader2Parser } from "./obj2/OBJLoader2Parser.js"; import { MeshReceiver } from "./obj2/shared/MeshReceiver.js"; import { MaterialHandler } from "./obj2/shared/MaterialHandler.js"; @@ -43,7 +43,7 @@ const OBJLoader2 = function ( manager ) { }; -OBJLoader2.OBJLOADER2_VERSION = '3.1.1'; +OBJLoader2.OBJLOADER2_VERSION = '3.2.0'; console.info( 'Using OBJLoader2 version: ' + OBJLoader2.OBJLOADER2_VERSION ); diff --git a/examples/jsm/loaders/OBJLoader2Parallel.d.ts b/examples/jsm/loaders/OBJLoader2Parallel.d.ts index fed7eda84766424273a0e006ca36e45f6d6c63e2..f2cdac74c33fbd9c2bc8dc400b1d7a51673aa0b7 100644 --- a/examples/jsm/loaders/OBJLoader2Parallel.d.ts +++ b/examples/jsm/loaders/OBJLoader2Parallel.d.ts @@ -12,7 +12,7 @@ export class OBJLoader2Parallel extends OBJLoader2 { executeParallel: boolean; workerExecutionSupport: WorkerExecutionSupport; - setPreferJsmWorker( preferJsmWorker: boolean ): this; + setJsmWorker( preferJsmWorker: boolean, jsmWorkerUrl: URL ): this; setExecuteParallel( executeParallel: boolean ): this; getWorkerExecutionSupport(): object; buildWorkerCode(): object; diff --git a/examples/jsm/loaders/OBJLoader2Parallel.js b/examples/jsm/loaders/OBJLoader2Parallel.js index 83f21aa9a5b862c8d71161e23bb1cf0b1fea609a..87eac7a56ddef84cc0dad93a19e5d842416ad77f 100644 --- a/examples/jsm/loaders/OBJLoader2Parallel.js +++ b/examples/jsm/loaders/OBJLoader2Parallel.js @@ -15,7 +15,7 @@ import { CodeSerializer } from "./obj2/utils/CodeSerializer.js"; import { OBJLoader2 } from "./OBJLoader2.js"; // Imports only related to worker (when standard workers (modules aren't supported) are used) -import { OBJLoader2Parser } from "./obj2/worker/parallel/OBJLoader2Parser.js"; +import { OBJLoader2Parser } from "./obj2/OBJLoader2Parser.js"; import { WorkerRunner, DefaultWorkerPayloadHandler, @@ -34,15 +34,16 @@ const OBJLoader2Parallel = function ( manager ) { OBJLoader2.call( this, manager ); this.preferJsmWorker = false; + this.jsmWorkerUrl = null; this.executeParallel = true; this.workerExecutionSupport = new WorkerExecutionSupport(); }; -OBJLoader2Parallel.OBJLOADER2_PARALLEL_VERSION = '3.1.2'; +OBJLoader2Parallel.OBJLOADER2_PARALLEL_VERSION = '3.2.0'; console.info( 'Using OBJLoader2Parallel version: ' + OBJLoader2Parallel.OBJLOADER2_PARALLEL_VERSION ); - +OBJLoader2Parallel.DEFAULT_JSM_WORKER_PATH = './jsm/loaders/obj2/worker/parallel/OBJLoader2JsmWorker.js'; OBJLoader2Parallel.prototype = Object.assign( Object.create( OBJLoader2.prototype ), { @@ -51,7 +52,7 @@ OBJLoader2Parallel.prototype = Object.assign( Object.create( OBJLoader2.prototyp /** * Execution of parse in parallel via Worker is default, but normal {OBJLoader2} parsing can be enforced via false here. * - * @param executeParallel True or False + * @param {boolean} executeParallel True or False * @return {OBJLoader2Parallel} */ setExecuteParallel: function ( executeParallel ) { @@ -63,12 +64,17 @@ OBJLoader2Parallel.prototype = Object.assign( Object.create( OBJLoader2.prototyp /** * Set whether jsm modules in workers should be used. This requires browser support which is currently only experimental. - * @param preferJsmWorker True or False + * @param {boolean} preferJsmWorker True or False + * @param {URL} jsmWorkerUrl Provide complete jsm worker URL otherwise relative path to this module may not be correct * @return {OBJLoader2Parallel} */ - setPreferJsmWorker: function ( preferJsmWorker ) { + setJsmWorker: function ( preferJsmWorker, jsmWorkerUrl ) { this.preferJsmWorker = preferJsmWorker === true; + if ( jsmWorkerUrl === undefined || jsmWorkerUrl === null ) { + throw "The url to the jsm worker is not valid. Aborting..." + } + this.jsmWorkerUrl = jsmWorkerUrl; return this; }, @@ -92,7 +98,7 @@ OBJLoader2Parallel.prototype = Object.assign( Object.create( OBJLoader2.prototyp let codeBuilderInstructions = new CodeBuilderInstructions( true, true, this.preferJsmWorker ); if ( codeBuilderInstructions.isSupportsJsmWorker() ) { - codeBuilderInstructions.setJsmWorkerFile( '../examples/loaders/jsm/obj2/worker/parallel/jsm/OBJLoader2Worker.js' ); + codeBuilderInstructions.setJsmWorkerUrl( this.jsmWorkerUrl ); } if ( codeBuilderInstructions.isSupportsStandardWorker() ) { diff --git a/examples/jsm/loaders/obj2/worker/parallel/OBJLoader2Parser.d.ts b/examples/jsm/loaders/obj2/OBJLoader2Parser.d.ts similarity index 100% rename from examples/jsm/loaders/obj2/worker/parallel/OBJLoader2Parser.d.ts rename to examples/jsm/loaders/obj2/OBJLoader2Parser.d.ts diff --git a/examples/jsm/loaders/obj2/worker/parallel/OBJLoader2Parser.js b/examples/jsm/loaders/obj2/OBJLoader2Parser.js similarity index 100% rename from examples/jsm/loaders/obj2/worker/parallel/OBJLoader2Parser.js rename to examples/jsm/loaders/obj2/OBJLoader2Parser.js diff --git a/examples/jsm/loaders/obj2/worker/main/WorkerExecutionSupport.d.ts b/examples/jsm/loaders/obj2/worker/main/WorkerExecutionSupport.d.ts index 38c1d8b16c1edc600150d83b4b26ca3746e96cf9..102666c417596504ddcc738545adce6b48d93b96 100644 --- a/examples/jsm/loaders/obj2/worker/main/WorkerExecutionSupport.d.ts +++ b/examples/jsm/loaders/obj2/worker/main/WorkerExecutionSupport.d.ts @@ -13,7 +13,7 @@ export class CodeBuilderInstructions { isSupportsStandardWorker(): boolean; isSupportsJsmWorker(): boolean; isPreferJsmWorker(): boolean; - setJsmWorkerFile( jsmWorkerFile: string ): void; + setJsmWorkerUrl( jsmWorkerUrl: string ): void; addStartCode( startCode: string ): void; addCodeFragment( code: string ): void; addLibraryImport( libraryPath: string ): void; diff --git a/examples/jsm/loaders/obj2/worker/main/WorkerExecutionSupport.js b/examples/jsm/loaders/obj2/worker/main/WorkerExecutionSupport.js index 326fdfc62bd8d049d1817f359b3e551d907920b3..85986c6c3d03a19632e8b1b54316687a97ddb30e 100644 --- a/examples/jsm/loaders/obj2/worker/main/WorkerExecutionSupport.js +++ b/examples/jsm/loaders/obj2/worker/main/WorkerExecutionSupport.js @@ -19,7 +19,7 @@ const CodeBuilderInstructions = function ( supportsStandardWorker, supportsJsmWo this.codeFragments = []; this.importStatements = []; - this.jsmWorkerFile = null; + this.jsmWorkerUrl = null; this.defaultGeometryType = 0; }; @@ -49,13 +49,13 @@ CodeBuilderInstructions.prototype = { /** * Set the full path to the module that contains the worker code. * - * @param {String} jsmWorkerFile + * @param {String} jsmWorkerUrl */ - setJsmWorkerFile: function ( jsmWorkerFile ) { + setJsmWorkerUrl: function ( jsmWorkerUrl ) { - if ( jsmWorkerFile !== undefined && jsmWorkerFile !== null ) { + if ( jsmWorkerUrl !== undefined && jsmWorkerUrl !== null ) { - this.jsmWorkerFile = jsmWorkerFile; + this.jsmWorkerUrl = jsmWorkerUrl; } @@ -127,7 +127,7 @@ const WorkerExecutionSupport = function () { this._reset(); }; -WorkerExecutionSupport.WORKER_SUPPORT_VERSION = '3.1.0'; +WorkerExecutionSupport.WORKER_SUPPORT_VERSION = '3.2.0'; console.info( 'Using WorkerSupport version: ' + WorkerExecutionSupport.WORKER_SUPPORT_VERSION ); @@ -289,10 +289,9 @@ WorkerExecutionSupport.prototype = { let workerAvailable = this._buildWorkerCheckPreconditions( true, timeLabel ); if ( ! workerAvailable ) { - let workerFileUrl = new URL( codeBuilderInstructions.jsmWorkerFile, window.location.href ).href; try { - let worker = new Worker( workerFileUrl, { type: "module" } ); + let worker = new Worker( codeBuilderInstructions.jsmWorkerUrl.href, { type: "module" } ); this._configureWorkerCommunication( worker, true, codeBuilderInstructions.defaultGeometryType, timeLabel ); } catch ( e ) { @@ -387,6 +386,7 @@ WorkerExecutionSupport.prototype = { }; this.worker.native.onmessage = scopedReceiveWorkerMessage; + this.worker.native.onerror = scopedReceiveWorkerMessage; if ( defaultGeometryType !== undefined && defaultGeometryType !== null ) { this.worker.workerRunner.defaultGeometryType = defaultGeometryType; @@ -418,9 +418,15 @@ WorkerExecutionSupport.prototype = { */ _receiveWorkerMessage: function ( event ) { + // fast-fail in case of error + if ( event.type === "error" ) { + + console.error( event ); + return; + + } let payload = event.data; let workerRunnerName = this.worker.workerRunner.name; - switch ( payload.cmd ) { case 'assetAvailable': diff --git a/examples/jsm/loaders/obj2/worker/parallel/jsm/OBJLoader2Worker.js b/examples/jsm/loaders/obj2/worker/parallel/OBJLoader2JsmWorker.js similarity index 73% rename from examples/jsm/loaders/obj2/worker/parallel/jsm/OBJLoader2Worker.js rename to examples/jsm/loaders/obj2/worker/parallel/OBJLoader2JsmWorker.js index c9f2de76ead706d44b1030839adf623d92ad9b55..001813aa3ae180666b06d6365679885b3a7b92f7 100644 --- a/examples/jsm/loaders/obj2/worker/parallel/jsm/OBJLoader2Worker.js +++ b/examples/jsm/loaders/obj2/worker/parallel/OBJLoader2JsmWorker.js @@ -3,10 +3,11 @@ * Development repository: https://github.com/kaisalmen/WWOBJLoader */ -import { OBJLoader2Parser } from "../OBJLoader2Parser.js"; +import { OBJLoader2Parser } from "../../OBJLoader2Parser.js"; + import { WorkerRunner, DefaultWorkerPayloadHandler -} from "../WorkerRunner.js"; +} from "./WorkerRunner.js"; new WorkerRunner( new DefaultWorkerPayloadHandler( new OBJLoader2Parser() ) ); diff --git a/examples/webgl_loader_obj2_options.html b/examples/webgl_loader_obj2_options.html index ef13e7827fc90f623705363bfe4208cc553a20c1..b6f9b8f356839b91395eb72ca5fcc099e12c53e6 100644 --- a/examples/webgl_loader_obj2_options.html +++ b/examples/webgl_loader_obj2_options.html @@ -44,7 +44,7 @@
- three.js - OBJLoader2 usage options + three.js - OBJLoader2 usage options
Use module workers with Chromium based browser (80+)
@@ -85,6 +85,8 @@ this.flatShading = false; this.doubleSide = false; + this.useJsmWorker = false; + this.loadCount = 6; this.cube = null; this.pivot = null; @@ -155,7 +157,8 @@ scope.pivot.add( local ); local.add( objLoader2.parse( content ) ); - scope._reportProgress( { detail: { text: 'Loading of ' + modelName + 'completed: ' + message } } ); + scope._reportProgress( { detail: { text: 'Loading of ' + modelName + ' completed: OBJLoader2#pase: Parsing completed' } } ); + scope.finalize(); } ); } @@ -176,7 +179,8 @@ let scope = this; function callbackOnLoad( object3d, message ) { local.add( object3d ); - scope._reportProgress( { detail: { text: 'Loading of ' + modelName + 'completed: ' + message } } ); + scope._reportProgress( { detail: { text: 'Loading of ' + modelName + ' completed: ' + message } } ); + scope.finalize(); } let materials = { @@ -185,6 +189,7 @@ let objLoader2Parallel = new OBJLoader2Parallel() .setModelName( modelName ) + .setJsmWorker( this.useJsmWorker, new URL( OBJLoader2Parallel.DEFAULT_JSM_WORKER_PATH, window.location.href ) ) .setCallbackOnLoad( callbackOnLoad ) .addMaterials( materials, true ); @@ -214,7 +219,8 @@ scope.pivot.add( local ); local.add( object3d ); - scope._reportProgress( { detail: { text: 'Loading of ' + modelName + 'completed: ' + message } } ); + scope._reportProgress( { detail: { text: 'Loading of ' + modelName + ' completed: ' + message } } ); + scope.finalize(); } function onLoadMtl ( mtlParseResult ) { @@ -238,12 +244,14 @@ this.pivot.add( local ); let objLoader2Parallel = new OBJLoader2Parallel() - .setModelName( modelName ); + .setModelName( modelName ) + .setJsmWorker( this.useJsmWorker, new URL( OBJLoader2Parallel.DEFAULT_JSM_WORKER_PATH, window.location.href ) ); let scope = this; function callbackOnLoad ( object3d, message ) { local.add( object3d ); - scope._reportProgress( { detail: { text: 'Loading of ' + modelName + 'completed: ' + message } } ); + scope._reportProgress( { detail: { text: 'Loading of ' + modelName + ' completed: ' + message } } ); + scope.finalize(); } function onLoadMtl ( mtlParseResult ) { objLoader2Parallel.addMaterials( MtlObjBridge.addMaterialsFromMtlLoader( mtlParseResult ), true ); @@ -269,7 +277,8 @@ let scope = this; function callbackOnLoad ( object3d, message ) { local.add( object3d ); - scope._reportProgress( { detail: { text: 'Loading of ' + objLoader2Parallel.modelName + 'completed: ' + message } } ); + scope._reportProgress( { detail: { text: 'Loading of ' + objLoader2Parallel.modelName + ' completed: ' + message } } ); + scope.finalize(); } objLoader2Parallel.load( 'models/obj/cerberus/Cerberus.obj', callbackOnLoad ); @@ -283,6 +292,7 @@ let objLoader2Parallel = new OBJLoader2Parallel() .setModelName( local.name ) + .setJsmWorker( this.useJsmWorker, new URL( OBJLoader2Parallel.DEFAULT_JSM_WORKER_PATH, window.location.href ) ) .setBaseObject3d( local ); // Configure WorkerExecutionSupport to not disregard worker after execution @@ -305,14 +315,20 @@ let scope = this; function callbackOnLoad ( object3d, message ) { - scope._reportProgress( { detail: { text: 'Loading of ' + objLoader2Parallel.modelName + 'completed: ' + message } } ); + scope._reportProgress( { detail: { text: 'Loading of ' + objLoader2Parallel.modelName + ' completed: ' + message } } ); + scope.finalize(); } objLoader2Parallel.load( 'models/obj/ninja/ninjaHead_Low.obj', callbackOnLoad ); }, finalize: function () { - this._reportProgress( { detail: { text: '' } } ); + this.loadCount--; + if ( this.loadCount === 0 ) { + + this._reportProgress( { detail: { text: '' } } ); + + } }, _reportProgress: function( event ) { @@ -408,15 +424,55 @@ this.traversalFunction( object3d.material ); } + }, + + executeLoading: function () { + // Load a file with OBJLoader2.parse on main + this.useParseMain(); + + // Load a file with OBJLoader2Parallel.parse in parallel in worker + this.useParseParallel(); + + // Load a file with OBJLoader.load on main + this.useLoadMain(); + + // Load a file with OBJLoader2Parallel.load in parallel in worker + this.useLoadParallel(); + + // Load a file with OBJLoader2Parallel.load on main with fallback to OBJLoader2.parse + this.useLoadMainFallback(); + + // Load a file with OBJLoader2Parallel.load in parallel in worker and add normals during onMeshAlter + this.useLoadParallelMeshAlter(); } }; let app = new WWOBJLoader2Example( document.getElementById( 'example' ) ); + let handleExecuteLoading; let wwObjLoader2Control = { flatShading: app.flatShading, - doubleSide: app.doubleSide + doubleSide: app.doubleSide, + useJsmWorker: app.useJsmWorker, + blockEvent: function ( event ) { + + event.stopPropagation(); + + }, + disableElement: function ( elementHandle ) { + + elementHandle.domElement.addEventListener( 'click', this.blockEvent, true ); + elementHandle.domElement.parentElement.style.pointerEvents = 'none'; + elementHandle.domElement.parentElement.style.opacity = 0.5; + + }, + executeLoading: function() { + + app.executeLoading(); + this.disableElement( handleExecuteLoading ); + + }, }; let menuDiv = document.getElementById( 'dat' ); @@ -426,19 +482,31 @@ } ); menuDiv.appendChild( gui.domElement ); - let folderOptions = gui.addFolder( 'WWOBJLoader2 Options' ); - let controlFlat = folderOptions.add( wwObjLoader2Control, 'flatShading' ).name( 'Flat Shading' ); + let folderRenderingOptions = gui.addFolder( 'Rendering Options' ); + let controlFlat = folderRenderingOptions.add( wwObjLoader2Control, 'flatShading' ).name( 'Flat Shading' ); controlFlat.onChange( function( value ) { console.log( 'Setting flatShading to: ' + value ); app.alterShading(); }); - let controlDouble = folderOptions.add( wwObjLoader2Control, 'doubleSide' ).name( 'Double Side Materials' ); + let controlDouble = folderRenderingOptions.add( wwObjLoader2Control, 'doubleSide' ).name( 'Double Side Materials' ); controlDouble.onChange( function( value ) { console.log( 'Setting doubleSide to: ' + value ); app.alterDouble(); }); - folderOptions.open(); + + let folderObjLoader2ParallelOptions = gui.addFolder( 'OBJLoader2Parallel Options' ); + let controlJsmWorker = folderObjLoader2ParallelOptions.add( wwObjLoader2Control, 'useJsmWorker' ).name( 'Use Module Workers' ); + controlJsmWorker.onChange( function( value ) { + console.log( 'Setting useJsmWorker to: ' + value ); + app.useJsmWorker = value; + }); + let folderExecution = gui.addFolder( 'Execution' ); + handleExecuteLoading = folderExecution.add( wwObjLoader2Control, 'executeLoading' ).name( 'Run' ); + handleExecuteLoading.domElement.id = 'startButton'; + folderRenderingOptions.open(); + folderObjLoader2ParallelOptions.open(); + folderExecution.open(); // init three.js example application @@ -459,25 +527,6 @@ // kick render loop render(); - // Load a file with OBJLoader2.parse on main - app.useParseMain(); - - // Load a file with OBJLoader2Parallel.parse in parallel in worker - app.useParseParallel(); - - // Load a file with OBJLoader.load on main - app.useLoadMain(); - - // Load a file with OBJLoader2Parallel.load in parallel in worker - app.useLoadParallel(); - - // Load a file with OBJLoader2Parallel.load on main with fallback to OBJLoader2.parse - app.useLoadMainFallback(); - - // Load a file with OBJLoader2Parallel.load in parallel in worker and add normals during onMeshAlter - app.useLoadParallelMeshAlter(); - app.finalize(); -