未验证 提交 4ef42a9b 编写于 作者: M Michael Herzog 提交者: GitHub

Merge pull request #18886 from kaisalmen/OBJ2LoaderParallel_ModuleWorkers

Module worker support in OBJLoader2Parallel and webgl_loader_obj2_options example
......@@ -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';
......
......@@ -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 );
......
......@@ -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;
......
......@@ -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() ) {
......
......@@ -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;
......
......@@ -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':
......
......@@ -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() ) );
......@@ -44,7 +44,7 @@
</div>
<div id="info">
<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - OBJLoader2 usage options
<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - OBJLoader2 usage options<br>Use module workers with Chromium based browser (80+)
<div id="feedback"></div>
</div>
......@@ -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();
</script>
</body>
</html>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册