Files
PointCloudWeb/PointCloudWeb.Web/public/Potree/libs/three.js/loaders/OBJLoader2Parallel.js
2021-08-04 21:30:59 +02:00

233 lines
6.6 KiB
JavaScript

/**
* Development repository: https://github.com/kaisalmen/WWOBJLoader
*/
// Imports only related to wrapper
import {
Object3D
} from '../../../build/three.module.js';
import {
CodeBuilderInstructions,
WorkerExecutionSupport
} from './obj2/worker/main/WorkerExecutionSupport.js';
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/OBJLoader2Parser.js';
import {
WorkerRunner,
DefaultWorkerPayloadHandler,
ObjectManipulator
} from './obj2/worker/parallel/WorkerRunner.js';
/**
* Creates a new OBJLoader2Parallel. Use it to load OBJ data from files or to parse OBJ data from arraybuffer.
* It extends {@link OBJLoader2} with the capability to run the parser in a web worker.
*
* @param [LoadingManager] manager The loadingManager for the loader to use. Default is {@link LoadingManager}
* @constructor
*/
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.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 ), {
constructor: OBJLoader2Parallel,
/**
* Execution of parse in parallel via Worker is default, but normal {OBJLoader2} parsing can be enforced via false here.
*
* @param {boolean} executeParallel True or False
* @return {OBJLoader2Parallel}
*/
setExecuteParallel: function ( executeParallel ) {
this.executeParallel = executeParallel === true;
return this;
},
/**
* Set whether jsm modules in workers should be used. This requires browser support which is currently only experimental.
* @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}
*/
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;
},
/**
* Allow to get hold of {@link WorkerExecutionSupport} for configuration purposes.
* @return {WorkerExecutionSupport}
*/
getWorkerExecutionSupport: function () {
return this.workerExecutionSupport;
},
/**
* Provide instructions on what is to be contained in the worker.
* @return {CodeBuilderInstructions}
*/
buildWorkerCode: function () {
const codeBuilderInstructions = new CodeBuilderInstructions( true, true, this.preferJsmWorker );
if ( codeBuilderInstructions.isSupportsJsmWorker() ) {
codeBuilderInstructions.setJsmWorkerUrl( this.jsmWorkerUrl );
}
if ( codeBuilderInstructions.isSupportsStandardWorker() ) {
const objectManipulator = new ObjectManipulator();
const defaultWorkerPayloadHandler = new DefaultWorkerPayloadHandler( this.parser );
const workerRunner = new WorkerRunner( {} );
codeBuilderInstructions.addCodeFragment( CodeSerializer.serializeClass( OBJLoader2Parser, this.parser ) );
codeBuilderInstructions.addCodeFragment( CodeSerializer.serializeClass( ObjectManipulator, objectManipulator ) );
codeBuilderInstructions.addCodeFragment( CodeSerializer.serializeClass( DefaultWorkerPayloadHandler, defaultWorkerPayloadHandler ) );
codeBuilderInstructions.addCodeFragment( CodeSerializer.serializeClass( WorkerRunner, workerRunner ) );
const startCode = 'new ' + workerRunner.constructor.name + '( new ' + defaultWorkerPayloadHandler.constructor.name + '( new ' + this.parser.constructor.name + '() ) );';
codeBuilderInstructions.addStartCode( startCode );
}
return codeBuilderInstructions;
},
/**
* See {@link OBJLoader2.load}
*/
load: function ( content, onLoad, onFileLoadProgress, onError, onMeshAlter ) {
const scope = this;
function interceptOnLoad( object3d, message ) {
if ( object3d.name === 'OBJLoader2ParallelDummy' ) {
if ( scope.parser.logging.enabled && scope.parser.logging.debug ) {
console.debug( 'Received dummy answer from OBJLoader2Parallel#parse' );
}
} else {
onLoad( object3d, message );
}
}
OBJLoader2.prototype.load.call( this, content, interceptOnLoad, onFileLoadProgress, onError, onMeshAlter );
},
/**
* See {@link OBJLoader2.parse}
* The callback onLoad needs to be set to be able to receive the content if used in parallel mode.
* Fallback is possible via {@link OBJLoader2Parallel#setExecuteParallel}.
*/
parse: function ( content ) {
if ( this.executeParallel ) {
if ( this.parser.callbacks.onLoad === this.parser._onLoad ) {
throw 'No callback other than the default callback was provided! Aborting!';
}
// check if worker has been initialize before. If yes, skip init
if ( ! this.workerExecutionSupport.isWorkerLoaded( this.preferJsmWorker ) ) {
this.workerExecutionSupport.buildWorker( this.buildWorkerCode() );
const scope = this;
const scopedOnAssetAvailable = function ( payload ) {
scope._onAssetAvailable( payload );
};
function scopedOnLoad( message ) {
scope.parser.callbacks.onLoad( scope.baseObject3d, message );
}
this.workerExecutionSupport.updateCallbacks( scopedOnAssetAvailable, scopedOnLoad );
}
// Create default materials beforehand, but do not override previously set materials (e.g. during init)
this.materialHandler.createDefaultMaterials( false );
this.workerExecutionSupport.executeParallel(
{
params: {
modelName: this.modelName,
instanceNo: this.instanceNo,
useIndices: this.parser.useIndices,
disregardNormals: this.parser.disregardNormals,
materialPerSmoothingGroup: this.parser.materialPerSmoothingGroup,
useOAsMesh: this.parser.useOAsMesh,
materials: this.materialHandler.getMaterialsJSON()
},
data: {
input: content,
options: null
},
logging: {
enabled: this.parser.logging.enabled,
debug: this.parser.logging.debug
}
} );
const dummy = new Object3D();
dummy.name = 'OBJLoader2ParallelDummy';
return dummy;
} else {
return OBJLoader2.prototype.parse.call( this, content );
}
},
} );
export { OBJLoader2Parallel };