Generic WorkerLoader

OBJLoader2 introduced LoaderSupport in R88. This separated the more generic Worker related functions from the OBJ format loader. My idea was that other loaders could use it to allow worker based loading where it makes sense.

I realized during discussion we had (#13263 and #13648) that this is not the right approach. LoaderSupport was over-freighted with functions that have been partially removed in R91, but any loader needs to depend on it.
It seems to be the better idea for to change the direction of the dependency and create a generic WorkerLoader that uses existing loaders and impose as little as possible on how Parsing must be organized.

LoaderSupport will disappear. I already have a WIP version of OBJLoader(2) that no longer depends on LoaderSupport (#13663). It should be replaced by a generic WorkerLoader integrating the useful Worker tools from LoaderSupport.

My overall idea for WorkerLoader looks as follows:
Any Loaders feature these methods where serializeParser is optional:

THREE.AnyLoader.prototype = function () {

	parse: function ( content ) {
	},
	
	load: function ( url, onLoad, onProgress, onError) {
	},

	serializeParser: function( serializeClassFunction, serializeObjectFunction ) {
	}
}

A Parser should ideally be:

  • independent of any other code (three or other libraries) which makes the Worker code a lot smaller and faster to load and use
  • Should isolate Mesh creation in a function allowing to pass from the Worker back to the Main in Transferables whereever possible

The loader is given to WorkerLoader which either uses the serializeParser from the provided loader, it allows to use an optional Parser which WorkerLoader tries to serialize itself or it loads the given files to the worker, where optionalParser could be used as code wrapper (handling Transferables for example).

THREE.WorkerLoader = function ( loader, optionalParser, extraLibs2Load ) {
	
	this.workerSupport = new THREE.WorkerLoader.WorkerSupport();
	this.loader = loader;
	
	var code;
	if ( optionalParser ) {
		
		code = this.workerSupport.serializeClass( optionalParser );
		
	} else {
		
		code = this.loader.serializeParser( this.workerSupport.serializeClass, this.workerSupport.serializeObject ),
		
	}
	this.workerSupport.validate( code, 'Parser', extraLibs2Load );
};

THREE.WorkerLoader.prototype = function () {
	
	constructor: THREE.WorkerLoader,

	parse: function( arrayBuffer, onLoad, onMesh ) {
		...
		this._runWorker( { ... } );
	},

	load: function ( url, onLoad, onProgress, onError, onMesh ) {
		...
		this._runWorker( { ... } );
	},
	
	execute: function ( automationInstructions ) {
		...
		this._runWorker( { ... } );
	},
	
	_runWorker: function ( buffersAndInstructions ) {
		this.workerSupport.run( buffersAndInstructions );
	}
}

Examples:
Option 1: Parser code is completely supplied by AnyLoader:

var workerLoader = new THREE.WorkerLoader( new AnyLoader() );
workerLoader.parse( arrayBuffer, ... );

Option 2: Parser code and additional libs are suppiled in addition to AnyLoader (provides possibility to supply any code inside Worker):

var workerLoader = new THREE.WorkerLoader( new AnyLoader(), AnyLoaderParserWrapper, [ 'examples/js/loader/AnyLoader.js', 'build/three.min.js' ] );
workerLoader.parse( arrayBuffer, ... );

Not yet fully working, but evolving WIP code is here will become visible in three.js branch soon (WWOBJLoader issue36):
https://github.com/kaisalmen/WWOBJLoader/blob/Issue36/src/loaders/WorkerLoader.js

Let me know what you think. Especially, if it fits your use cases. Thanks.

Three.js version
  • Dev
  • r91

Author: Fantashit

2 thoughts on “Generic WorkerLoader

Comments are closed.