From 5a390957b7cd61899d353b47050bd7bfff32141e Mon Sep 17 00:00:00 2001 From: Kai Salmen Date: Wed, 7 Mar 2018 23:03:59 +0100 Subject: [PATCH] OBJLoader2 V2.4.0: - three.js issue 13197: - Added forceWorkerDataCopy to THREE.LoaderSupport.WorkerSupport and THREE.LoaderSupport.WorkerDirector - THREE.OBJLoader2 handles cached resources properly. This increases overall performance as no unnecessary reloads are requested. - THREE.OBJLoader2: Reduced Parser complexity: - Simplified slash counting used for face type detection - One buildFace fucntion is used for all four face types, lines and points including indices (=vertex reduction) creation if wanted. - String processing (o, g, mtllib and usemtl) just concatenates chars - Overall speed improvements due simpler code paths - Removed THREE.LoaderSupport.ConsoleLogger: Added setLogging function as replacement where. Console logging is behind boolean flags. - Removed THREE.LoaderSupport.LoaderBase: Many functions are coupled with OBJLoader2. It was simply not generic enough and added unneeded complexity. - Reduced THREE.LoaderSupport.PrepData to minimum set of generic functions. Simple properties are added by demand and are no longer enforced. - Renamed THREE.LoaderSupport.Builder to THREE.LoaderSupport.MeshBuilder - Updated documentation --- docs/examples/loaders/LoaderSupport.html | 351 ++------ docs/examples/loaders/OBJLoader2.html | 59 +- examples/js/loaders/LoaderSupport.js | 872 +++++++------------ examples/js/loaders/OBJLoader2.js | 635 +++++++++----- examples/models/obj/verify/verify.html | 8 +- examples/webgl_loader_obj2.html | 2 +- examples/webgl_loader_obj2_meshspray.html | 105 ++- examples/webgl_loader_obj2_options.html | 6 +- examples/webgl_loader_obj2_run_director.html | 30 +- 9 files changed, 922 insertions(+), 1146 deletions(-) diff --git a/docs/examples/loaders/LoaderSupport.html b/docs/examples/loaders/LoaderSupport.html index 9f72525ee8..b304cec794 100644 --- a/docs/examples/loaders/LoaderSupport.html +++ b/docs/examples/loaders/LoaderSupport.html @@ -19,11 +19,10 @@ [page:LoaderSupport.WorkerSupport]
[page:LoaderSupport.WorkerRunnerRefImpl]
[page:LoaderSupport.WorkerDirector]
+ [page:LoaderSupport.ResourceDescriptor]
[page:LoaderSupport.PrepData]
- [page:LoaderSupport.LoaderBase]
[page:LoaderSupport.Callbacks]
[page:LoaderSupport.Validator]
- [page:LoaderSupport.ConsoleLogger]

Example

@@ -45,6 +44,22 @@

Methods

+

[method:null setLogging] ( [param:Boolean enabled], [param:Boolean debug] )

+
+ [page:Boolean enabled] True or false.
+ [page:Boolean debug] True or false. +
+
+ Enable or disable logging in general (except warn and error), plus enable or disable debug logging. +
+ + +

[method:null init] ()

+
+ Initializes the Builder (currently only default material initialisation). +
+ +

[method:null setMaterials] ( Array of [param:Material materials] )

Array of [page:Material materials] - Array of [page:Material Materials] @@ -61,8 +76,6 @@
Delegates processing of the payload (mesh building or material update) to the corresponding functions (BW-compatibility).
-
-

[method:Array buildMeshes] ( Object meshPayload )

@@ -72,8 +85,6 @@
Builds one or multiple meshes from the data described in the payload (buffers, params, material info).
-
-

[method:null updateMaterials] ( Object materialPayload )

@@ -83,16 +94,12 @@
Updates the materials with contained material objects (sync) or from alteration instructions (async).
-
-

[method:Object getMaterialsJSON] ()

Returns the mapping object of material name and corresponding jsonified material.
-
-

[method:Object getMaterials] ()

@@ -144,10 +151,7 @@

WorkerSupport

Constructor

-

WorkerSupport( [param:LoaderSupport.ConsoleLogger logger] )

-
- [page:LoaderSupport.ConsoleLogger logger] - logger to be used -
+

WorkerSupport()

This class provides means to transform existing parser code into a web worker. It defines a simple communication protocol which allows to configure the worker and receive raw mesh data during execution. @@ -156,6 +160,25 @@

Methods

+

[method:null setLogging]( [param:Boolean enabled], [param:Boolean debug] )

+
+ [page:Boolean enabled] True or false.
+ [page:Boolean debug] True or false. +
+
+ Enable or disable logging in general (except warn and error), plus enable or disable debug logging. +
+ + +

[method:null setForceWorkerDataCopy]( [param:Boolean forceWorkerDataCopy] )

+
+ [page:Boolean forceWorkerDataCopy] True or false. +
+
+ Forces all ArrayBuffers to be transferred to worker to be copied. +
+ +

[method:null validate] ( [param:Function functionCodeBuilder], Array of [param:String libLocations], [param:String libPath], [param:LoaderSupport.WorkerRunnerRefImpl runnerImpl] )

[page:Function functionCodeBuilder] - Function that is invoked with funcBuildObject and funcBuildSingleton that allows stringification of objects and singletons.
@@ -233,10 +256,9 @@

WorkerDirector

Constructor

-

WorkerDirector( [param:String classDef], [param:LoaderSupport.ConsoleLogger logger] )

+

WorkerDirector( [param:String classDef] )

- [page:String classDef] - Class definition to be used for construction
- [page:LoaderSupport.ConsoleLogger logger] - logger to be used + [page:String classDef] - Class definition to be used for construction
Orchestrate loading of multiple OBJ files/data from an instruction queue with a configurable amount of workers (1-16).
@@ -250,6 +272,25 @@

Methods

+

[method:null setLogging]( [param:Boolean enabled], [param:Boolean debug] )

+
+ [page:Boolean enabled] True or false.
+ [page:Boolean debug] True or false. +
+
+ Enable or disable logging in general (except warn and error), plus enable or disable debug logging. +
+ + +

[method:null setForceWorkerDataCopy]( [param:Boolean forceWorkerDataCopy] )

+
+ [page:Boolean forceWorkerDataCopy] True or false. +
+
+ Forces all ArrayBuffers to be transferred to worker to be copied. +
+ +

[method:null prepareWorkers]( [param:WWOBJLoader2.Callbacks globalCallbacks], [param:Number maxQueueSize], [param:Number maxWebWorkers] )

[page:LoaderSupport.Callbacks globalCallbacks] - Register global callbacks used by all web workers
@@ -309,199 +350,88 @@
Sets the CORS string to be used.
+
+
-

PrepData

+

ResourceDescriptor

Constructor

-

PrepData( [param:String modelName] )

+

ResourceDescriptor( [param:String url], [param:String extension] )

- [page:String modelName] - Overall name of the model + [page:String url] - URL to the file
+ [page:String extension] - The file extension (type)
- Configuration instructions to be used by run method. + A resource description used by [page:LoaderSupport.PrepData] and others.
-

Methods

-

[method:null setStreamMeshesTo] ( [param:Object3D streamMeshesTo] )

-
- [page:Object3D streamMeshesTo] - Object already attached to scenegraph where new meshes will be attached to -
-
- Set the node where the loaded objects will be attached directly. -
- - -

[method:null setMaterialPerSmoothingGroup] ( [param:boolean materialPerSmoothingGroup] )

-
- [page:boolean materialPerSmoothingGroup] -
-
- Tells whether a material shall be created per smoothing group. -
- - -

[method:null setUseIndices]( [param:Boolean useIndices] )

-
- [page:Boolean useIndices] - Default is false -
-
- Instructs loaders to create indexed [page:BufferGeometry]. -
- - -

[method:null setDisregardNormals]( [param:Boolean disregardNormals] )

-
- [page:Boolean disregardNormals] -
-
- Tells whether normals should be completely disregarded and regenerated. -
- - -

[method:Callbacks getCallbacks]()

-
- Returns all callbacks as [page:LoaderSupport.Callbacks]. -
- - -

[method:null setCrossOrigin]( [param:String crossOrigin] )

-
- [page:String crossOrigin] - CORS value -
-
- Sets the CORS string to be used. -
- - -

[method:null addResource]( [param:LoaderSupport.ResourceDescriptor resource] )

-
- [page:LoaderSupport.ResourceDescriptor resource] -
-
- Add a resource description. -
- - -

[method:null setUseAsync]( [param:Boolean useAsync] )

+

[method:null setContent]( [param:Object content )

- [page:Boolean useAsync] + [page:Object content] - The file content as ArrayBuffer or text
- If true uses async loading with worker, if false loads data synchronously. + Set the content of this resource


-

LoaderBase

+

PrepData

Constructor

-

LoaderBase( [param:LoadingManager manager], [param:LoaderSupport.ConsoleLogger logger] )

+

PrepData( [param:String modelName] )

- [page:LoadingManager manager] - The [page:LoadingManager loadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager]. - [page:LoaderSupport.ConsoleLogger logger] - logger to be used + [page:String modelName] - Overall name of the model
- Base class to be used by Loaders that provide load, parse, parseAsync and run + Configuration instructions to be used by run method.

Methods

-

[method:null load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError], [param:Function onMeshAlter], [param:boolean useAsync] )

+

[method:null setLogging]( [param:Boolean enabled], [param:Boolean debug] )

- [page:String url] - A string containing the path/URL of the file to be loaded.
- [page:Function onLoad] - A function to be called after loading is successfully completed. The function receives loaded [page:Object3D] as an argument.
- [page:Function onProgress] - (optional) A function to be called while the loading is in progress. The argument will be the XMLHttpRequest instance, which contains [page:Integer total] and [page:Integer loaded] bytes.
- [page:Function onError] - (optional) A function to be called if an error occurs during loading. The function receives the error as an argument.
- [page:Function onMeshAlter] - (optional) A function to be called after a new mesh raw data becomes available for alteration.
- [page:boolean useAsync] - (optional) If true, uses async loading with worker, if false loads data synchronously. + [page:Boolean enabled] True or false.
+ [page:Boolean debug] True or false.
- Use this convenient method to load a file at the given URL. By default the fileLoader uses an ArrayBuffer. -
- -

[method:ConsoleLogger checkResourceDescriptorFiles] ( [param:THREE.LoaderSupport.ResourceDescriptor resources], [param:Object fileDesc] )

-
- [page:THREE.LoaderSupport.ResourceDescriptor resources] - Array of {@link THREE.LoaderSupport.ResourceDescriptor} - [page:Object fileDesc] - Object describing which resources are of interest (ext, type (string or UInt8Array) and ignore (boolean)) -
-
- Identify files or content of interest from an Array of {@link THREE.LoaderSupport.ResourceDescriptor}. Returns Object with each "ext" and the corresponding {@link THREE.LoaderSupport.ResourceDescriptor} -
- - -

[method:ConsoleLogger getLogger] ()

-
- Returns [page:LoaderSupport.ConsoleLogger]. -
- - -

[method:null setModelName] ( [param:String modelName] )

-
- [page:String modelName] -
-
- Set the name of the model. + Enable or disable logging in general (except warn and error), plus enable or disable debug logging.
-

[method:null setPath] ( [param:String path] )

-
- [page:String path] - URL -
-
- The URL of the base path. -
- - -

[method:null setStreamMeshesTo] ( [param:Object3D streamMeshesTo] )

-
- [page:Object3D streamMeshesTo] - Object already attached to scenegraph where new meshes will be attached to -
-
- Set the node where the loaded objects will be attached directly. -
- - -

[method:null setMaterials] ( Array of [param:Material materials] )

-
- Array of [page:Material materials] - Array of [page:Material Materials] -
+

[method:Callbacks getCallbacks]()

- Set materials loaded by MTLLoader or any other supplier of an Array of [page:Material Materials]. + Returns all callbacks as [page:LoaderSupport.Callbacks].
-

[method:null setUseIndices]( [param:Boolean useIndices] )

+

[method:null addResource]( [param:LoaderSupport.ResourceDescriptor resource] )

- [page:Boolean useIndices] + [page:LoaderSupport.ResourceDescriptor resource] Adds a [page:LoaderSupport.ResourceDescriptor]
- Instructs loaders to create indexed [page:BufferGeometry]. + Add a resource description.
-

[method:null setDisregardNormals]( [param:Boolean disregardNormals] )

+

[method:null checkResourceDescriptorFiles] ( [param:LoaderSupport.ResourceDescriptor resources], [param:Object fileDesc] )

- [page:Boolean disregardNormals] + [page:LoaderSupport.ResourceDescriptor resources] - Array of [page:LoaderSupport.ResourceDescriptor]
+ [page:Object fileDesc] - Object describing which resources are of interest (ext, type (string or UInt8Array) and ignore (boolean))
- Tells whether normals should be completely disregarded and regenerated. + Identify files or content of interest from an Array of [page:LoaderSupport.ResourceDescriptor]. + Returns Object with each "ext" and the corresponding [page:LoaderSupport.ResourceDescriptor]
-

[method:null onProgress]( [param:String type], [param:String text], [param:Number numericalValue] )

-
- [page:String type] - The type of event
- [page:String text] - Textual description of the event
- [page:Number numericalValue] - Numerical value describing the progress -
+

[method:PrepData clone] ()

- Announce feedback which is give to the registered [page:LoaderSupport.Callbacks]. + Clones this object and returns it afterwards. Callbacks and resources are not cloned deep (references!).


@@ -578,7 +508,7 @@

[method:null verifyInput]( [param:Object input], [param:Object defaultValue] )

- [page:Object input] - Can be anything + [page:Object input] - Can be anything
[page:Object defaultValue] - Can be anything
@@ -587,109 +517,6 @@

- -

ConsoleLogger

-

Constructor

- -

ConsoleLogger( [param:Boolean enabled], [param:Boolean debug] )

-
- [page:Boolean enabled] - Tell if logger is enabled. - [page:Boolean debug] - Toggle debug logging. -
- Logging wrapper for console. -
- - -

Methods

- -

[method:null setDebug]( [param:Boolean debug] )

-
- [page:Boolean debug] - True or False -
-
- Enable or disable debug logging. -
- - -

[method:Boolean isDebug]()

-
- Returns if is enabled and debug. -
- -

[method:null setEnabled]( [param:Boolean enabled] )

-
- [page:Boolean enabled] - True or False -
-
- Enable or disable info, debug and time logging. -
- - -

[method:Boolean isEnabled]()

-
- Returns if is enabled. -
- - -

[method:null logDebug]( [param:String message], Array of [param:String additional] )

-
- [page:String message] - Message to log - Array of [page:String additional] - Array of [page:String strings] containing additional content to be logged -
-
- Log a debug message if enabled and debug is set. -
- - -

[method:null logInfo]( [param:String message], Array of [param:String additional] )

-
- [page:String message] - Message to log - Array of [page:String additional] - Array of [page:String strings] containing additional content to be logged -
-
- Log an info message if enabled. -
- - -

[method:null logWarn]( [param:String message], Array of [param:String additional] )

-
- [page:String message] - Message to log - Array of [page:String additional] - Array of [page:String strings] containing additional content to be logged -
-
- Log a warn message (always). -
- - -

[method:null logError]( [param:String message], Array of [param:String additional] )

-
- [page:String message] - Message to log - Array of [page:String additional] - Array of [page:String strings] containing additional content to be logged -
-
- Log an error message (always). -
- - -

[method:null logTimeStart]( [param:String id] )

-
- [page:String id] - Time identification -
-
- Start time measurement with provided id. -
- - -

[method:null logTimeEnd]( [param:String id] )

-
- [page:String id] - Time identification -
-
- Stop time measurement started with provided id. -
-
-
-

Source

[link:https://github.com/mrdoob/three.js/blob/master/examples/js/loaders/LoaderSupport.js examples/js/loaders/LoaderSupport.js] diff --git a/docs/examples/loaders/OBJLoader2.html b/docs/examples/loaders/OBJLoader2.html index 68c5353b23..c43db2507a 100644 --- a/docs/examples/loaders/OBJLoader2.html +++ b/docs/examples/loaders/OBJLoader2.html @@ -71,7 +71,18 @@
-

[method:null load] => [param:LoaderSupport.LoaderBase.load]

+

[method:null load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError], [param:Function onMeshAlter], [param:boolean useAsync] )

+
+ [page:String url] - A string containing the path/URL of the file to be loaded.
+ [page:Function onLoad] - A function to be called after loading is successfully completed. The function receives loaded [page:Object3D] as an argument.
+ [page:Function onProgress] - (optional) A function to be called while the loading is in progress. The argument will be the XMLHttpRequest instance, which contains [page:Integer total] and [page:Integer loaded] bytes.
+ [page:Function onError] - (optional) A function to be called if an error occurs during loading. The function receives the error as an argument.
+ [page:Function onMeshAlter] - (optional) A function to be called after a new mesh raw data becomes available for alteration.
+ [page:boolean useAsync] - (optional) If true, uses async loading with worker, if false loads data synchronously. +
+
+ Use this convenient method to load a file at the given URL. By default the fileLoader uses an ArrayBuffer. +

[method:null run]( [param:LoaderSupport.PrepData params], [param:LoaderSupport.WorkerSupport workerSupportExternal] )

@@ -84,23 +95,13 @@
-

[method:Object checkResourceDescriptorFiles] => [param:LoaderSupport.LoaderBase.checkResourceDescriptorFiles]

- - -

[method:null setMaterialPerSmoothingGroup] ( [param:boolean materialPerSmoothingGroup] )

+

[method:null setLogging]( [param:Boolean enabled], [param:Boolean debug] )

- [page:boolean materialPerSmoothingGroup] + [page:Boolean enabled] True or false.
+ [page:Boolean debug] True or false.
- Tells whether a material shall be created per smoothing group. -
- - -

The following methods are inherited from [page:LoaderSupport.Commons]

- -

[method:ConsoleLogger getLogger] ()

-
- Returns [page:LoaderSupport.ConsoleLogger]. + Enable or disable logging in general (except warn and error), plus enable or disable debug logging.
@@ -158,12 +159,32 @@
+

[method:null setMaterialPerSmoothingGroup] ( [param:boolean materialPerSmoothingGroup] )

+
+ [page:boolean materialPerSmoothingGroup] +
+
+ Tells whether a material shall be created per smoothing group. +
+ + +

[method:null onProgress]( [param:String type], [param:String text], [param:Number numericalValue] )

+
+ [page:String type] - The type of event
+ [page:String text] - Textual description of the event
+ [page:Number numericalValue] - Numerical value describing the progress +
+
+ Announce feedback which is give to the registered [page:LoaderSupport.Callbacks]. +
+ +

[method:null loadMtl]( [param:String url], [param:Object content], [param:Function callbackOnLoad], [param:String crossOrigin], [param:Object materialOptions])

- [page:String url] - URL to the file - [page:Object content] - The file content as arraybuffer or text - [page:Function callbackOnLoad] - Callback to be called after successful load - [page:String crossOrigin] - (optional) CORS value + [page:String url] - URL to the file
+ [page:Object content] - The file content as arraybuffer or text
+ [page:Function callbackOnLoad] - Callback to be called after successful load
+ [page:String crossOrigin] - (optional) CORS value
[page:Function materialOptions] - (optional) Set material loading options for MTLLoader
diff --git a/examples/js/loaders/LoaderSupport.js b/examples/js/loaders/LoaderSupport.js index fbfa907a5a..6eb9552785 100644 --- a/examples/js/loaders/LoaderSupport.js +++ b/examples/js/loaders/LoaderSupport.js @@ -35,147 +35,7 @@ THREE.LoaderSupport.Validator = { /** - * Logging wrapper for console. - * @class - * - * @param {boolean} enabled=true Tell if logger is enabled. - * @param {boolean} debug=false Toggle debug logging. - */ -THREE.LoaderSupport.ConsoleLogger = (function () { - - function ConsoleLogger( enabled, debug ) { - this.enabled = enabled !== false; - this.debug = debug === true; - } - - /** - * Enable or disable debug logging. - * @memberOf THREE.LoaderSupport.ConsoleLogger - * - * @param {boolean} debug True or False - */ - ConsoleLogger.prototype.setDebug = function ( debug ) { - this.debug = debug === true; - }; - - /** - * Returns if is enabled and debug. - * @memberOf THREE.LoaderSupport.ConsoleLogger - * - * @returns {boolean} - */ - ConsoleLogger.prototype.isDebug = function () { - return this.isEnabled() && this.debug; - }; - - /** - * Enable or disable info, debug and time logging. - * @memberOf THREE.LoaderSupport.ConsoleLogger - * - * @param {boolean} enabled True or False - */ - ConsoleLogger.prototype.setEnabled = function ( enabled ) { - this.enabled = enabled === true; - }; - - /** - * Returns if is enabled. - * @memberOf THREE.LoaderSupport.ConsoleLogger - * - * @returns {boolean} - */ - ConsoleLogger.prototype.isEnabled = function () { - return this.enabled; - }; - - /** - * Log a debug message if enabled and debug is set. - * @memberOf THREE.LoaderSupport.ConsoleLogger - * - * @param {string} message Message to log - * @param {string[]} additional Array of strings containing additional content to be logged - * - */ - ConsoleLogger.prototype.logDebug = function ( message, additional ) { - if ( this.enabled && this.debug ) { - - this._createStatement( message, 'Additional content:', additional, function ( output ) { console.debug( output ) } ); - - } - }; - - /** - * Log an info message if enabled. - * @memberOf THREE.LoaderSupport.ConsoleLogger - * - * @param {string} message Message to log - * @param {string[]} additional Array of strings containing additional content to be logged - */ - ConsoleLogger.prototype.logInfo = function ( message, additional ) { - if ( this.enabled ) { - - this._createStatement( message, 'Additional content:', additional, function ( output ) { console.info( output ) } ); - - } - }; - - /** - * Log a warn message (always). - * @memberOf THREE.LoaderSupport.ConsoleLogger - * - * @param {string} message Message to log - * @param {string[]} additional Array of strings containing additional content to be logged - */ - ConsoleLogger.prototype.logWarn = function ( message, additional ) { - this._createStatement( message, 'Additional content:', additional, function ( output ) { console.warn( output ) } ); - }; - - /** - * Log an error message (always). - * @memberOf THREE.LoaderSupport.ConsoleLogger - * - * @param {string} message Message to log - * @param {string[]} additional Array of strings containing additional content to be logged - */ - ConsoleLogger.prototype.logError = function ( message, additional ) { - this._createStatement( message, 'Additional content:', additional, function ( output ) { console.error( output ) } ); - }; - - /** - * Start time measurement with provided id. - * @memberOf THREE.LoaderSupport.ConsoleLogger - * - * @param {string} id Time identification - */ - ConsoleLogger.prototype.logTimeStart = function ( id ) { - if ( this.enabled ) console.time( id ); - }; - - /** - * Stop time measurement started with provided id. - * @memberOf THREE.LoaderSupport.ConsoleLogger - * - * @param {string} id Time identification - */ - ConsoleLogger.prototype.logTimeEnd = function ( id ) { - if ( this.enabled ) console.timeEnd( id ); - }; - - ConsoleLogger.prototype._createStatement = function ( message, addHeader, additional, logFunction ) { - var output = message; - if ( Array.isArray( additional ) ) { - - output += '\n' + addHeader + '\n' + additional.join( '\n' ); - - } - logFunction( output ); - }; - - return ConsoleLogger; -})(); - -/** - * Callbacks utilized by loaders and builder. + * Callbacks utilized by loaders and builders. * @class */ THREE.LoaderSupport.Callbacks = (function () { @@ -316,7 +176,7 @@ THREE.LoaderSupport.ResourceDescriptor = (function () { } /** - * Set the content of this resource (String) + * Set the content of this resource * @memberOf THREE.LoaderSupport.ResourceDescriptor * * @param {Object} content The file content as arraybuffer or text @@ -338,55 +198,25 @@ THREE.LoaderSupport.PrepData = (function () { var Validator = THREE.LoaderSupport.Validator; function PrepData( modelName ) { + this.logging = { + enabled: true, + debug: false + }; this.modelName = Validator.verifyInput( modelName, '' ); this.resources = []; - this.streamMeshesTo = null; - this.materialPerSmoothingGroup = false; - this.useIndices = false; - this.disregardNormals = false; this.callbacks = new THREE.LoaderSupport.Callbacks(); - this.crossOrigin; - this.useAsync = false; } /** - * Set the node where the loaded objects will be attached directly. - * @memberOf THREE.LoaderSupport.PrepData - * - * @param {THREE.Object3D} streamMeshesTo Object already attached to scenegraph where new meshes will be attached to - */ - PrepData.prototype.setStreamMeshesTo = function ( streamMeshesTo ) { - this.streamMeshesTo = Validator.verifyInput( streamMeshesTo, null ); - }; - - /** - * Tells whether a material shall be created per smoothing group. + * Enable or disable logging in general (except warn and error), plus enable or disable debug logging. * @memberOf THREE.LoaderSupport.PrepData * - * @param {boolean} materialPerSmoothingGroup=false + * @param {boolean} enabled True or false. + * @param {boolean} debug True or false. */ - PrepData.prototype.setMaterialPerSmoothingGroup = function ( materialPerSmoothingGroup ) { - this.materialPerSmoothingGroup = materialPerSmoothingGroup === true; - }; - - /** - * Tells whether indices should be used - * @memberOf THREE.LoaderSupport.PrepData - * - * @param {boolean} useIndices=false - */ - PrepData.prototype.setUseIndices = function ( useIndices ) { - this.useIndices = useIndices === true; - }; - - /** - * Tells whether normals should be completely disregarded and regenerated. - * @memberOf THREE.LoaderSupport.PrepData - * - * @param {boolean} disregardNormals=false - */ - PrepData.prototype.setDisregardNormals = function ( disregardNormals ) { - this.disregardNormals = disregardNormals === true; + PrepData.prototype.setLogging = function ( enabled, debug ) { + this.logging.enabled = enabled === true; + this.logging.debug = debug === true; }; /** @@ -399,55 +229,115 @@ THREE.LoaderSupport.PrepData = (function () { return this.callbacks; }; - /** - * Sets the CORS string to be used. - * @memberOf THREE.LoaderSupport.PrepData - * - * @param {string} crossOrigin CORS value - */ - PrepData.prototype.setCrossOrigin = function ( crossOrigin ) { - this.crossOrigin = crossOrigin; - }; - /** * Add a resource description. * @memberOf THREE.LoaderSupport.PrepData * - * @param {THREE.LoaderSupport.ResourceDescriptor} + * @param {THREE.LoaderSupport.ResourceDescriptor} Adds a {@link THREE.LoaderSupport.ResourceDescriptor} */ PrepData.prototype.addResource = function ( resource ) { this.resources.push( resource ); }; /** - * If true uses async loading with worker, if false loads data synchronously. - * @memberOf THREE.LoaderSupport.PrepData - * - * @param {boolean} useAsync - */ - PrepData.prototype.setUseAsync = function ( useAsync ) { - this.useAsync = useAsync === true; - }; - - /** - * Clones this object and returns it afterwards. + * Clones this object and returns it afterwards. Callbacks and resources are not cloned deep (references!). * @memberOf THREE.LoaderSupport.PrepData * * @returns {@link THREE.LoaderSupport.PrepData} */ PrepData.prototype.clone = function () { var clone = new THREE.LoaderSupport.PrepData( this.modelName ); + clone.logging.enabled = this.logging.enabled; + clone.logging.debug = this.logging.debug; clone.resources = this.resources; - clone.streamMeshesTo = this.streamMeshesTo; - clone.materialPerSmoothingGroup = this.materialPerSmoothingGroup; - clone.useIndices = this.useIndices; - clone.disregardNormals = this.disregardNormals; clone.callbacks = this.callbacks; - clone.crossOrigin = this.crossOrigin; - clone.useAsync = this.useAsync; + + var property, value; + for ( property in this ) { + + value = this[ property ]; + if ( ! clone.hasOwnProperty( property ) && typeof this[ property ] !== 'function' ) { + + clone[ property ] = value; + + } + } + return clone; }; + + /** + * Identify files or content of interest from an Array of {@link THREE.LoaderSupport.ResourceDescriptor}. + * @memberOf THREE.LoaderSupport.PrepData + * + * @param {THREE.LoaderSupport.ResourceDescriptor[]} resources Array of {@link THREE.LoaderSupport.ResourceDescriptor} + * @param Object fileDesc Object describing which resources are of interest (ext, type (string or UInt8Array) and ignore (boolean)) + * @returns {{}} Object with each "ext" and the corresponding {@link THREE.LoaderSupport.ResourceDescriptor} + */ + PrepData.prototype.checkResourceDescriptorFiles = function ( resources, fileDesc ) { + var resource, triple, i, found; + var result = {}; + + for ( var index in resources ) { + + resource = resources[ index ]; + found = false; + if ( ! Validator.isValid( resource.name ) ) continue; + if ( Validator.isValid( resource.content ) ) { + + for ( i = 0; i < fileDesc.length && !found; i++ ) { + + triple = fileDesc[ i ]; + if ( resource.extension.toLowerCase() === triple.ext.toLowerCase() ) { + + if ( triple.ignore ) { + + found = true; + + } else if ( triple.type === "ArrayBuffer" ) { + + // fast-fail on bad type + if ( ! ( resource.content instanceof ArrayBuffer || resource.content instanceof Uint8Array ) ) throw 'Provided content is not of type ArrayBuffer! Aborting...'; + result[ triple.ext ] = resource; + found = true; + + } else if ( triple.type === "String" ) { + + if ( ! ( typeof( resource.content ) === 'string' || resource.content instanceof String) ) throw 'Provided content is not of type String! Aborting...'; + result[ triple.ext ] = resource; + found = true; + + } + + } + + } + if ( !found ) throw 'Unidentified resource "' + resource.name + '": ' + resource.url; + + } else { + + // fast-fail on bad type + if ( ! ( typeof( resource.name ) === 'string' || resource.name instanceof String ) ) throw 'Provided file is not properly defined! Aborting...'; + for ( i = 0; i < fileDesc.length && !found; i++ ) { + + triple = fileDesc[ i ]; + if ( resource.extension.toLowerCase() === triple.ext.toLowerCase() ) { + + if ( ! triple.ignore ) result[ triple.ext ] = resource; + found = true; + + } + + } + if ( !found ) throw 'Unidentified resource "' + resource.name + '": ' + resource.url; + + } + } + + return result; + }; + return PrepData; })(); @@ -456,22 +346,41 @@ THREE.LoaderSupport.PrepData = (function () { * Supports vertex, vertexColor, normal, uv and index buffers. * @class */ -THREE.LoaderSupport.Builder = (function () { +THREE.LoaderSupport.MeshBuilder = (function () { - var LOADER_BUILDER_VERSION = '1.1.1'; + var LOADER_MESH_BUILDER_VERSION = '1.2.0'; var Validator = THREE.LoaderSupport.Validator; - var ConsoleLogger = THREE.LoaderSupport.ConsoleLogger; - function Builder( logger ) { - this.logger = Validator.verifyInput( logger, new ConsoleLogger() ); - this.logger.logInfo( 'Using THREE.LoaderSupport.Builder version: ' + LOADER_BUILDER_VERSION ); + function MeshBuilder() { + console.info( 'Using THREE.LoaderSupport.MeshBuilder version: ' + LOADER_MESH_BUILDER_VERSION ); + this.logging = { + enabled: true, + debug: false + }; + this.callbacks = new THREE.LoaderSupport.Callbacks(); this.materials = []; - this._createDefaultMaterials(); } - Builder.prototype._createDefaultMaterials = function () { + /** + * Enable or disable logging in general (except warn and error), plus enable or disable debug logging. + * @memberOf THREE.LoaderSupport.MeshBuilder + * + * @param {boolean} enabled True or false. + * @param {boolean} debug True or false. + */ + MeshBuilder.prototype.setLogging = function ( enabled, debug ) { + this.logging.enabled = enabled === true; + this.logging.debug = debug === true; + }; + + /** + * Initializes the MeshBuilder (currently only default material initialisation). + * @memberOf THREE.LoaderSupport.MeshBuilder + * + */ + MeshBuilder.prototype.init = function () { var defaultMaterial = new THREE.MeshStandardMaterial( { color: 0xDCF1FF } ); defaultMaterial.name = 'defaultMaterial'; @@ -482,7 +391,7 @@ THREE.LoaderSupport.Builder = (function () { var defaultLineMaterial = new THREE.LineBasicMaterial(); defaultLineMaterial.name = 'defaultLineMaterial'; - var defaultPointMaterial = new THREE.PointsMaterial( { size: 1, sizeAttenuation: false } ); + var defaultPointMaterial = new THREE.PointsMaterial( { size: 1 } ); defaultPointMaterial.name = 'defaultPointMaterial'; var runtimeMaterials = {}; @@ -505,11 +414,11 @@ THREE.LoaderSupport.Builder = (function () { /** * Set materials loaded by any supplier of an Array of {@link THREE.Material}. - * @memberOf THREE.LoaderSupport.Builder + * @memberOf THREE.LoaderSupport.MeshBuilder * * @param {THREE.Material[]} materials Array of {@link THREE.Material} */ - Builder.prototype.setMaterials = function ( materials ) { + MeshBuilder.prototype.setMaterials = function ( materials ) { var payload = { cmd: 'materialData', materials: { @@ -521,7 +430,7 @@ THREE.LoaderSupport.Builder = (function () { this.updateMaterials( payload ); }; - Builder.prototype._setCallbacks = function ( callbacks ) { + MeshBuilder.prototype._setCallbacks = function ( callbacks ) { if ( Validator.isValid( callbacks.onProgress ) ) this.callbacks.setCallbackOnProgress( callbacks.onProgress ); if ( Validator.isValid( callbacks.onMeshAlter ) ) this.callbacks.setCallbackOnMeshAlter( callbacks.onMeshAlter ); if ( Validator.isValid( callbacks.onLoad ) ) this.callbacks.setCallbackOnLoad( callbacks.onLoad ); @@ -530,12 +439,12 @@ THREE.LoaderSupport.Builder = (function () { /** * Delegates processing of the payload (mesh building or material update) to the corresponding functions (BW-compatibility). - * @memberOf THREE.LoaderSupport.Builder + * @memberOf THREE.LoaderSupport.MeshBuilder * * @param {Object} payload Raw Mesh or Material descriptions. * @returns {THREE.Mesh[]} mesh Array of {@link THREE.Mesh} or null in case of material update */ - Builder.prototype.processPayload = function ( payload ) { + MeshBuilder.prototype.processPayload = function ( payload ) { if ( payload.cmd === 'meshData' ) { return this.buildMeshes( payload ); @@ -550,12 +459,12 @@ THREE.LoaderSupport.Builder = (function () { /** * Builds one or multiple meshes from the data described in the payload (buffers, params, material info). - * @memberOf THREE.LoaderSupport.Builder + * @memberOf THREE.LoaderSupport.MeshBuilder * * @param {Object} meshPayload Raw mesh description (buffers, params, materials) used to build one to many meshes. * @returns {THREE.Mesh[]} mesh Array of {@link THREE.Mesh} */ - Builder.prototype.buildMeshes = function ( meshPayload ) { + MeshBuilder.prototype.buildMeshes = function ( meshPayload ) { var meshName = meshPayload.params.meshName; var bufferGeometry = new THREE.BufferGeometry(); @@ -688,7 +597,7 @@ THREE.LoaderSupport.Builder = (function () { var callbackOnProgress = this.callbacks.onProgress; if ( Validator.isValid( callbackOnProgress ) ) { - var event = new CustomEvent( 'BuilderEvent', { + var event = new CustomEvent( 'MeshBuilderEvent', { detail: { type: 'progress', modelName: meshPayload.params.meshName, @@ -705,11 +614,11 @@ THREE.LoaderSupport.Builder = (function () { /** * Updates the materials with contained material objects (sync) or from alteration instructions (async). - * @memberOf THREE.LoaderSupport.Builder + * @memberOf THREE.LoaderSupport.MeshBuilder * * @param {Object} materialPayload Material update instructions */ - Builder.prototype.updateMaterials = function ( materialPayload ) { + MeshBuilder.prototype.updateMaterials = function ( materialPayload ) { var material, materialName; var materialCloneInstructions = materialPayload.materials.materialCloneInstructions; if ( Validator.isValid( materialCloneInstructions ) ) { @@ -734,7 +643,7 @@ THREE.LoaderSupport.Builder = (function () { } else { - this.logger.logWarn( 'Requested material "' + materialNameOrg + '" is not available!' ); + console.warn( 'Requested material "' + materialNameOrg + '" is not available!' ); } } @@ -750,7 +659,7 @@ THREE.LoaderSupport.Builder = (function () { if ( Validator.isValid( materialJson ) ) { material = loader.parse( materialJson ); - this.logger.logInfo( 'De-serialized material with name "' + materialName + '" will be added.' ); + if ( this.logging.enabled ) console.info( 'De-serialized material with name "' + materialName + '" will be added.' ); this.materials[ materialName ] = material; } @@ -764,7 +673,7 @@ THREE.LoaderSupport.Builder = (function () { for ( materialName in materials ) { material = materials[ materialName ]; - this.logger.logInfo( 'Material with name "' + materialName + '" will be added.' ); + if ( this.logging.enabled ) console.info( 'Material with name "' + materialName + '" will be added.' ); this.materials[ materialName ] = material; } @@ -777,7 +686,7 @@ THREE.LoaderSupport.Builder = (function () { * * @returns {Object} Map of Materials in JSON representation */ - Builder.prototype.getMaterialsJSON = function () { + MeshBuilder.prototype.getMaterialsJSON = function () { var materialsJSON = {}; var material; for ( var materialName in this.materials ) { @@ -794,296 +703,11 @@ THREE.LoaderSupport.Builder = (function () { * * @returns {Object} Map of {@link THREE.Material} */ - Builder.prototype.getMaterials = function () { + MeshBuilder.prototype.getMaterials = function () { return this.materials; }; - return Builder; -})(); - -/** - * Base class to be used by Loaders that provide load, parse, parseAsync and run - * @class - * - * @param {THREE.DefaultLoadingManager} [manager] The loadingManager for the loader to use. Default is {@link THREE.DefaultLoadingManager} - * @param {THREE.LoaderSupport.ConsoleLogger} logger logger to be used - */ -THREE.LoaderSupport.LoaderBase = (function () { - - var Validator = THREE.LoaderSupport.Validator; - var ConsoleLogger = THREE.LoaderSupport.ConsoleLogger; - - function LoaderBase( manager, logger ) { - this.manager = Validator.verifyInput( manager, THREE.DefaultLoadingManager ); - this.logger = Validator.verifyInput( logger, new ConsoleLogger() ); - - this.fileLoader = new THREE.FileLoader( this.manager ); - this.fileLoader.setResponseType( 'arraybuffer' ); - - this.modelName = ''; - this.instanceNo = 0; - this.path = ''; - this.useIndices = false; - this.disregardNormals = false; - - this.loaderRootNode = new THREE.Group(); - this.builder = new THREE.LoaderSupport.Builder( this.logger ); - this.callbacks = new THREE.LoaderSupport.Callbacks(); - } - - LoaderBase.prototype._applyPrepData = function ( prepData ) { - if ( Validator.isValid( prepData ) ) { - - this.setModelName( prepData.modelName ); - this.setStreamMeshesTo( prepData.streamMeshesTo ); - this.builder.setMaterials( prepData.materials ); - this.setUseIndices( prepData.useIndices ); - this.setDisregardNormals( prepData.disregardNormals ); - - this._setCallbacks( prepData.getCallbacks() ); - } - }; - - LoaderBase.prototype._setCallbacks = function ( callbacks ) { - if ( Validator.isValid( callbacks.onProgress ) ) this.callbacks.setCallbackOnProgress( callbacks.onProgress ); - if ( Validator.isValid( callbacks.onMeshAlter ) ) this.callbacks.setCallbackOnMeshAlter( callbacks.onMeshAlter ); - if ( Validator.isValid( callbacks.onLoad ) ) this.callbacks.setCallbackOnLoad( callbacks.onLoad ); - if ( Validator.isValid( callbacks.onLoadMaterials ) ) this.callbacks.setCallbackOnLoadMaterials( callbacks.onLoadMaterials ); - - this.builder._setCallbacks( this.callbacks ); - }; - - /** - * Provides access to console logging wrapper. - * - * @returns {THREE.LoaderSupport.ConsoleLogger} - */ - LoaderBase.prototype.getLogger = function () { - return this.logger; - }; - - /** - * Set the name of the model. - * @memberOf THREE.LoaderSupport.LoaderBase - * - * @param {string} modelName - */ - LoaderBase.prototype.setModelName = function ( modelName ) { - this.modelName = Validator.verifyInput( modelName, this.modelName ); - }; - - /** - * The URL of the base path. - * @memberOf THREE.LoaderSupport.LoaderBase - * - * @param {string} path URL - */ - LoaderBase.prototype.setPath = function ( path ) { - this.path = Validator.verifyInput( path, this.path ); - }; - - /** - * Set the node where the loaded objects will be attached directly. - * @memberOf THREE.LoaderSupport.LoaderBase - * - * @param {THREE.Object3D} streamMeshesTo Object already attached to scenegraph where new meshes will be attached to - */ - LoaderBase.prototype.setStreamMeshesTo = function ( streamMeshesTo ) { - this.loaderRootNode = Validator.verifyInput( streamMeshesTo, this.loaderRootNode ); - }; - - /** - * Set materials loaded by MTLLoader or any other supplier of an Array of {@link THREE.Material}. - * @memberOf THREE.LoaderSupport.LoaderBase - * - * @param {THREE.Material[]} materials Array of {@link THREE.Material} - */ - LoaderBase.prototype.setMaterials = function ( materials ) { - this.builder.setMaterials( materials ); - }; - - /** - * Instructs loaders to create indexed {@link THREE.BufferGeometry}. - * @memberOf THREE.LoaderSupport.LoaderBase - * - * @param {boolean} useIndices=false - */ - LoaderBase.prototype.setUseIndices = function ( useIndices ) { - this.useIndices = useIndices === true; - }; - - /** - * Tells whether normals should be completely disregarded and regenerated. - * @memberOf THREE.LoaderSupport.LoaderBase - * - * @param {boolean} disregardNormals=false - */ - LoaderBase.prototype.setDisregardNormals = function ( disregardNormals ) { - this.disregardNormals = disregardNormals === true; - }; - - /** - * Announce feedback which is give to the registered callbacks. - * @memberOf THREE.LoaderSupport.LoaderBase - * @private - * - * @param {string} type The type of event - * @param {string} text Textual description of the event - * @param {number} numericalValue Numerical value describing the progress - */ - LoaderBase.prototype.onProgress = function ( type, text, numericalValue ) { - var content = Validator.isValid( text ) ? text: ''; - var event = { - detail: { - type: type, - modelName: this.modelName, - instanceNo: this.instanceNo, - text: content, - numericalValue: numericalValue - } - }; - - if ( Validator.isValid( this.callbacks.onProgress ) ) this.callbacks.onProgress( event ); - - this.logger.logDebug( content ); - }; - - /** - * Use this convenient method to load a file at the given URL. By default the fileLoader uses an ArrayBuffer. - * @memberOf THREE.LoaderSupport.LoaderBase - * - * @param {string} url A string containing the path/URL of the file to be loaded. - * @param {callback} onLoad A function to be called after loading is successfully completed. The function receives loaded Object3D as an argument. - * @param {callback} [onProgress] A function to be called while the loading is in progress. The argument will be the XMLHttpRequest instance, which contains total and Integer bytes. - * @param {callback} [onError] A function to be called if an error occurs during loading. The function receives the error as an argument. - * @param {callback} [onMeshAlter] A function to be called after a new mesh raw data becomes available for alteration. - * @param {boolean} [useAsync] If true, uses async loading with worker, if false loads data synchronously. - */ - LoaderBase.prototype.load = function ( url, onLoad, onProgress, onError, onMeshAlter, useAsync ) { - var scope = this; - if ( ! Validator.isValid( onProgress ) ) { - var numericalValueRef = 0; - var numericalValue = 0; - onProgress = function ( event ) { - if ( ! event.lengthComputable ) return; - - numericalValue = event.loaded / event.total; - if ( numericalValue > numericalValueRef ) { - - numericalValueRef = numericalValue; - var output = 'Download of "' + url + '": ' + ( numericalValue * 100 ).toFixed( 2 ) + '%'; - scope.onProgress( 'progressLoad', output, numericalValue ); - - } - }; - } - - if ( ! Validator.isValid( onError ) ) { - onError = function ( event ) { - var output = 'Error occurred while downloading "' + url + '"'; - scope.logger.logError( output + ': ' + event ); - scope.onProgress( 'error', output, -1 ); - }; - } - - this.fileLoader.setPath( this.path ); - this.fileLoader.load( url, function ( content ) { - if ( useAsync ) { - - scope.parseAsync( content, onLoad ); - - } else { - - var callbacks = new THREE.LoaderSupport.Callbacks(); - callbacks.setCallbackOnMeshAlter( onMeshAlter ); - scope._setCallbacks( callbacks ); - onLoad( - { - detail: { - loaderRootNode: scope.parse( content ), - modelName: scope.modelName, - instanceNo: scope.instanceNo - } - } - ); - - } - - }, onProgress, onError ); - - }; - - /** - * Identify files or content of interest from an Array of {@link THREE.LoaderSupport.ResourceDescriptor}. - * - * @param {THREE.LoaderSupport.ResourceDescriptor[]} resources Array of {@link THREE.LoaderSupport.ResourceDescriptor} - * @param Object fileDesc Object describing which resources are of interest (ext, type (string or UInt8Array) and ignore (boolean)) - * @returns {{}} Object with each "ext" and the corresponding {@link THREE.LoaderSupport.ResourceDescriptor} - */ - LoaderBase.prototype.checkResourceDescriptorFiles = function ( resources, fileDesc ) { - var resource, triple, i, found; - var result = {}; - - for ( var index in resources ) { - - resource = resources[ index ]; - found = false; - if ( ! Validator.isValid( resource.name ) ) continue; - if ( Validator.isValid( resource.content ) ) { - - for ( i = 0; i < fileDesc.length && !found; i++ ) { - - triple = fileDesc[ i ]; - if ( resource.extension.toLowerCase() === triple.ext.toLowerCase() ) { - - if ( triple.ignore ) { - - found = true; - - } else if ( triple.type === "Uint8Array" ) { - - // fast-fail on bad type - if ( ! ( resource.content instanceof Uint8Array ) ) throw 'Provided content is not of type arraybuffer! Aborting...'; - result[ triple.ext ] = resource; - found = true; - - } else if ( triple.type === "String" ) { - - if ( ! (typeof(resource.content) === 'string' || resource.content instanceof String) ) throw 'Provided content is not of type String! Aborting...'; - result[ triple.ext ] = resource; - found = true; - - } - - } - - } - if ( !found ) throw 'Unidentified resource "' + resource.name + '": ' + resource.url; - - } else { - - // fast-fail on bad type - if ( ! ( typeof( resource.name ) === 'string' || resource.name instanceof String ) ) throw 'Provided file is not properly defined! Aborting...'; - for ( i = 0; i < fileDesc.length && !found; i++ ) { - - triple = fileDesc[ i ]; - if ( resource.extension.toLowerCase() === triple.ext.toLowerCase() ) { - - if ( ! triple.ignore ) result[ triple.ext ] = resource; - found = true; - - } - - } - if ( !found ) throw 'Unidentified resource "' + resource.name + '": ' + resource.url; - - } - } - - return result; - }; - - return LoaderBase; + return MeshBuilder; })(); /** @@ -1133,31 +757,29 @@ THREE.LoaderSupport.WorkerRunnerRefImpl = (function () { * @param {Object} payload Raw mesh description (buffers, params, materials) used to build one to many meshes. */ WorkerRunnerRefImpl.prototype.processMessage = function ( payload ) { - var logEnabled = payload.logger.enabled; - var logDebug = payload.logger.enabled; if ( payload.cmd === 'run' ) { var callbacks = { - callbackBuilder: function ( payload ) { + callbackMeshBuilder: function ( payload ) { self.postMessage( payload ); }, callbackProgress: function ( text ) { - if ( logEnabled && logDebug ) console.debug( 'WorkerRunner: progress: ' + text ); + if ( payload.logging.enabled && payload.logging.debug ) console.debug( 'WorkerRunner: progress: ' + text ); } }; // Parser is expected to be named as such var parser = new Parser(); - if ( typeof parser[ 'setLogConfig' ] === 'function' ) parser.setLogConfig( logEnabled, logDebug ); + if ( typeof parser[ 'setLogging' ] === 'function' ) parser.setLogging( payload.logging.enabled, payload.logging.debug ); this.applyProperties( parser, payload.params ); this.applyProperties( parser, payload.materials ); this.applyProperties( parser, callbacks ); parser.workerScope = self; parser.parse( payload.data.input, payload.data.options ); - if ( logEnabled ) console.log( 'WorkerRunner: Run complete!' ); + if ( payload.logging.enabled ) console.log( 'WorkerRunner: Run complete!' ); - callbacks.callbackBuilder( { + callbacks.callbackMeshBuilder( { cmd: 'complete', msg: 'WorkerRunner completed run.' } ); @@ -1176,32 +798,43 @@ THREE.LoaderSupport.WorkerRunnerRefImpl = (function () { * This class provides means to transform existing parser code into a web worker. It defines a simple communication protocol * which allows to configure the worker and receive raw mesh data during execution. * @class - * - * @param {THREE.LoaderSupport.ConsoleLogger} logger logger to be used */ THREE.LoaderSupport.WorkerSupport = (function () { - var WORKER_SUPPORT_VERSION = '2.1.2'; + var WORKER_SUPPORT_VERSION = '2.2.0'; var Validator = THREE.LoaderSupport.Validator; var LoaderWorker = (function () { - function LoaderWorker( logger ) { - this.logger = Validator.verifyInput( logger, new THREE.LoaderSupport.ConsoleLogger() ); + function LoaderWorker() { this._reset(); } LoaderWorker.prototype._reset = function () { + this.logging = { + enabled: true, + debug: false + }; this.worker = null; this.runnerImplName = null; this.callbacks = { - builder: null, + meshBuilder: null, onLoad: null }; this.terminateRequested = false; this.queuedMessage = null; this.started = false; + this.forceCopy = false; + }; + + LoaderWorker.prototype.setLogging = function ( enabled, debug ) { + this.logging.enabled = enabled === true; + this.logging.debug = debug === true; + }; + + LoaderWorker.prototype.setForceCopy = function ( forceCopy ) { + this.forceCopy = forceCopy === true; }; LoaderWorker.prototype.initWorker = function ( code, runnerImplName ) { @@ -1226,7 +859,7 @@ THREE.LoaderSupport.WorkerSupport = (function () { case 'meshData': case 'materialData': case 'imageData': - this.runtimeRef.callbacks.builder( payload ); + this.runtimeRef.callbacks.meshBuilder( payload ); break; case 'complete': @@ -1236,35 +869,35 @@ THREE.LoaderSupport.WorkerSupport = (function () { if ( this.runtimeRef.terminateRequested ) { - this.runtimeRef.logger.logInfo( 'WorkerSupport [' + this.runtimeRef.runnerImplName + ']: Run is complete. Terminating application on request!' ); + if ( this.runtimeRef.logging.enabled ) console.info( 'WorkerSupport [' + this.runtimeRef.runnerImplName + ']: Run is complete. Terminating application on request!' ); this.runtimeRef._terminate(); } break; case 'error': - this.runtimeRef.logger.logError( 'WorkerSupport [' + this.runtimeRef.runnerImplName + ']: Reported error: ' + payload.msg ); + console.error( 'WorkerSupport [' + this.runtimeRef.runnerImplName + ']: Reported error: ' + payload.msg ); this.runtimeRef.queuedMessage = null; this.started = false; this.runtimeRef.callbacks.onLoad( payload.msg ); if ( this.runtimeRef.terminateRequested ) { - this.runtimeRef.logger.logInfo( 'WorkerSupport [' + this.runtimeRef.runnerImplName + ']: Run reported error. Terminating application on request!' ); + if ( this.runtimeRef.logging.enabled ) console.info( 'WorkerSupport [' + this.runtimeRef.runnerImplName + ']: Run reported error. Terminating application on request!' ); this.runtimeRef._terminate(); } break; default: - this.runtimeRef.logger.logError( 'WorkerSupport [' + this.runtimeRef.runnerImplName + ']: Received unknown command: ' + payload.cmd ); + console.error( 'WorkerSupport [' + this.runtimeRef.runnerImplName + ']: Received unknown command: ' + payload.cmd ); break; } }; - LoaderWorker.prototype.setCallbacks = function ( builder, onLoad ) { - this.callbacks.builder = Validator.verifyInput( builder, this.callbacks.builder ); + LoaderWorker.prototype.setCallbacks = function ( meshBuilder, onLoad ) { + this.callbacks.meshBuilder = Validator.verifyInput( meshBuilder, this.callbacks.meshBuilder ); this.callbacks.onLoad = Validator.verifyInput( onLoad, this.callbacks.onLoad ); }; @@ -1280,17 +913,17 @@ THREE.LoaderSupport.WorkerSupport = (function () { this.started = true; } - if ( ! Validator.isValid( this.callbacks.builder ) ) throw 'Unable to run as no "builder" callback is set.'; + if ( ! Validator.isValid( this.callbacks.meshBuilder ) ) throw 'Unable to run as no "MeshBuilder" callback is set.'; if ( ! Validator.isValid( this.callbacks.onLoad ) ) throw 'Unable to run as no "onLoad" callback is set.'; if ( payload.cmd !== 'run' ) payload.cmd = 'run'; - if ( Validator.isValid( payload.logger ) ) { + if ( Validator.isValid( payload.logging ) ) { - payload.logger.enabled = Validator.verifyInput( payload.logger.enabled, true ); - payload.logger.debug = Validator.verifyInput( payload.logger.debug, false ); + payload.logging.enabled = payload.logging.enabled === true; + payload.logging.debug = payload.logging.debug === true; } else { - payload.logger = { + payload.logging = { enabled: true, debug: false } @@ -1304,7 +937,17 @@ THREE.LoaderSupport.WorkerSupport = (function () { if ( this.queuedMessage.data.input instanceof ArrayBuffer ) { - this.worker.postMessage( this.queuedMessage, [ this.queuedMessage.data.input ] ); + var content; + if ( this.forceCopy ) { + + content = this.queuedMessage.data.input.slice( 0 ); + + } else { + + content = this.queuedMessage.data.input; + + } + this.worker.postMessage( this.queuedMessage, [ content ] ); } else { @@ -1319,7 +962,7 @@ THREE.LoaderSupport.WorkerSupport = (function () { this.terminateRequested = terminateRequested === true; if ( this.terminateRequested && Validator.isValid( this.worker ) && ! Validator.isValid( this.queuedMessage ) && this.started ) { - this.logger.logInfo( 'Worker is terminated immediately as it is not running!' ); + if ( this.logging.enabled ) console.info( 'Worker is terminated immediately as it is not running!' ); this._terminate(); } @@ -1334,18 +977,44 @@ THREE.LoaderSupport.WorkerSupport = (function () { })(); - function WorkerSupport( logger ) { - this.logger = Validator.verifyInput( logger, new THREE.LoaderSupport.ConsoleLogger() ); - this.logger.logInfo( 'Using THREE.LoaderSupport.WorkerSupport version: ' + WORKER_SUPPORT_VERSION ); + function WorkerSupport() { + console.info( 'Using THREE.LoaderSupport.WorkerSupport version: ' + WORKER_SUPPORT_VERSION ); + this.logging = { + enabled: true, + debug: false + }; // check worker support first if ( window.Worker === undefined ) throw "This browser does not support web workers!"; if ( window.Blob === undefined ) throw "This browser does not support Blob!"; if ( typeof window.URL.createObjectURL !== 'function' ) throw "This browser does not support Object creation from URL!"; - this.loaderWorker = new LoaderWorker( this.logger ); + this.loaderWorker = new LoaderWorker(); } + /** + * Enable or disable logging in general (except warn and error), plus enable or disable debug logging. + * @memberOf THREE.LoaderSupport.WorkerSupport + * + * @param {boolean} enabled True or false. + * @param {boolean} debug True or false. + */ + WorkerSupport.prototype.setLogging = function ( enabled, debug ) { + this.logging.enabled = enabled === true; + this.logging.debug = debug === true; + this.loaderWorker.setLogging( this.logging.enabled, this.logging.debug ); + }; + + /** + * Forces all ArrayBuffers to be transferred to worker to be copied. + * @memberOf THREE.LoaderSupport.WorkerSupport + * + * @param {boolean} forceWorkerDataCopy True or false. + */ + WorkerSupport.prototype.setForceWorkerDataCopy = function ( forceWorkerDataCopy ) { + this.loaderWorker.setForceCopy( forceWorkerDataCopy ); + }; + /** * Validate the status of worker code and the derived worker. * @memberOf THREE.LoaderSupport.WorkerSupport @@ -1359,22 +1028,25 @@ THREE.LoaderSupport.WorkerSupport = (function () { WorkerSupport.prototype.validate = function ( functionCodeBuilder, parserName, libLocations, libPath, runnerImpl ) { if ( Validator.isValid( this.loaderWorker.worker ) ) return; - this.logger.logInfo( 'WorkerSupport: Building worker code...' ); - this.logger.logTimeStart( 'buildWebWorkerCode' ); + if ( this.logging.enabled ) { + + console.info( 'WorkerSupport: Building worker code...' ); + console.time( 'buildWebWorkerCode' ); + } if ( Validator.isValid( runnerImpl ) ) { - this.logger.logInfo( 'WorkerSupport: Using "' + runnerImpl.name + '" as Runner class for worker.' ); + if ( this.logging.enabled ) console.info( 'WorkerSupport: Using "' + runnerImpl.name + '" as Runner class for worker.' ); } else { runnerImpl = THREE.LoaderSupport.WorkerRunnerRefImpl; - this.logger.logInfo( 'WorkerSupport: Using DEFAULT "THREE.LoaderSupport.WorkerRunnerRefImpl" as Runner class for worker.' ); + if ( this.logging.enabled ) console.info( 'WorkerSupport: Using DEFAULT "THREE.LoaderSupport.WorkerRunnerRefImpl" as Runner class for worker.' ); } var userWorkerCode = functionCodeBuilder( buildObject, buildSingleton ); - userWorkerCode += 'var Parser = '+ parserName + ';\n\n'; + userWorkerCode += 'var Parser = '+ parserName + ';\n\n'; userWorkerCode += buildSingleton( runnerImpl.name, runnerImpl ); userWorkerCode += 'new ' + runnerImpl.name + '();\n\n'; @@ -1386,7 +1058,7 @@ THREE.LoaderSupport.WorkerSupport = (function () { if ( locations.length === 0 ) { scope.loaderWorker.initWorker( libsContent + userWorkerCode, runnerImpl.name ); - scope.logger.logTimeEnd( 'buildWebWorkerCode' ); + if ( scope.logging.enabled ) console.timeEnd( 'buildWebWorkerCode' ); } else { @@ -1408,7 +1080,7 @@ THREE.LoaderSupport.WorkerSupport = (function () { } else { this.loaderWorker.initWorker( userWorkerCode, runnerImpl.name ); - this.logger.logTimeEnd( 'buildWebWorkerCode' ); + if ( this.logging.enabled ) console.timeEnd( 'buildWebWorkerCode' ); } }; @@ -1417,11 +1089,11 @@ THREE.LoaderSupport.WorkerSupport = (function () { * Specify functions that should be build when new raw mesh data becomes available and when the parser is finished. * @memberOf THREE.LoaderSupport.WorkerSupport * - * @param {Function} builder The builder function. Default is {@link THREE.LoaderSupport.Builder}. + * @param {Function} meshBuilder The mesh builder function. Default is {@link THREE.LoaderSupport.MeshBuilder}. * @param {Function} onLoad The function that is called when parsing is complete. */ - WorkerSupport.prototype.setCallbacks = function ( builder, onLoad ) { - this.loaderWorker.setCallbacks( builder, onLoad ); + WorkerSupport.prototype.setCallbacks = function ( meshBuilder, onLoad ) { + this.loaderWorker.setCallbacks( meshBuilder, onLoad ); }; /** @@ -1476,11 +1148,12 @@ THREE.LoaderSupport.WorkerSupport = (function () { return objectString; }; - var buildSingleton = function ( fullName, object, internalName ) { + var buildSingleton = function ( fullName, object, internalName, basePrototypeName, ignoreFunctions ) { var objectString = ''; var objectName = ( Validator.isValid( internalName ) ) ? internalName : object.name; var funcString, objectPart, constructorString; + ignoreFunctions = Validator.verifyInput( ignoreFunctions, [] ); for ( var name in object.prototype ) { objectPart = object.prototype[ name ]; @@ -1492,25 +1165,39 @@ THREE.LoaderSupport.WorkerSupport = (function () { } else if ( typeof objectPart === 'function' ) { - funcString = objectPart.toString(); - objectString += '\t' + objectName + '.prototype.' + name + ' = ' + funcString + ';\n\n'; + if ( ignoreFunctions.indexOf( name ) < 0 ) { + + funcString = objectPart.toString(); + objectString += '\t' + objectName + '.prototype.' + name + ' = ' + funcString + ';\n\n'; + + } } } objectString += '\treturn ' + objectName + ';\n'; objectString += '})();\n\n'; + + var inheritanceBlock = ''; + if ( Validator.isValid( basePrototypeName ) ) { + + inheritanceBlock += '\n'; + inheritanceBlock += objectName + '.prototype = Object.create( ' + basePrototypeName + '.prototype );\n'; + inheritanceBlock += objectName + '.constructor = ' + objectName + ';\n'; + inheritanceBlock += '\n'; + } if ( ! Validator.isValid( constructorString ) ) { constructorString = fullName + ' = (function () {\n\n'; - constructorString += '\t' + object.prototype.constructor.toString() + '\n\n'; + constructorString += inheritanceBlock + '\t' + object.prototype.constructor.toString() + '\n\n'; objectString = constructorString + objectString; } else { - objectString = fullName + ' = (function () {\n\n' + constructorString + objectString; + objectString = fullName + ' = (function () {\n\n' + inheritanceBlock + constructorString + objectString; } + return objectString; }; @@ -1529,20 +1216,22 @@ THREE.LoaderSupport.WorkerSupport = (function () { * @class * * @param {string} classDef Class definition to be used for construction - * @param {THREE.LoaderSupport.ConsoleLogger} logger logger to be used */ THREE.LoaderSupport.WorkerDirector = (function () { - var LOADER_WORKER_DIRECTOR_VERSION = '2.1.0'; + var LOADER_WORKER_DIRECTOR_VERSION = '2.2.0'; var Validator = THREE.LoaderSupport.Validator; var MAX_WEB_WORKER = 16; var MAX_QUEUE_SIZE = 8192; - function WorkerDirector( classDef, logger ) { - this.logger = Validator.verifyInput( logger, new THREE.LoaderSupport.ConsoleLogger() ); - this.logger.logInfo( 'Using THREE.LoaderSupport.WorkerDirector version: ' + LOADER_WORKER_DIRECTOR_VERSION ); + function WorkerDirector( classDef ) { + console.info( 'Using THREE.LoaderSupport.WorkerDirector version: ' + LOADER_WORKER_DIRECTOR_VERSION ); + this.logging = { + enabled: true, + debug: false + }; this.maxQueueSize = MAX_QUEUE_SIZE ; this.maxWebWorkers = MAX_WEB_WORKER; @@ -1553,7 +1242,8 @@ THREE.LoaderSupport.WorkerDirector = (function () { this.workerDescription = { classDef: classDef, globalCallbacks: {}, - workerSupports: {} + workerSupports: {}, + forceWorkerDataCopy: true }; this.objectsCompleted = 0; this.instructionQueue = []; @@ -1562,6 +1252,18 @@ THREE.LoaderSupport.WorkerDirector = (function () { this.callbackOnFinishedProcessing = null; } + /** + * Enable or disable logging in general (except warn and error), plus enable or disable debug logging. + * @memberOf THREE.LoaderSupport.WorkerDirector + * + * @param {boolean} enabled True or false. + * @param {boolean} debug True or false. + */ + WorkerDirector.prototype.setLogging = function ( enabled, debug ) { + this.logging.enabled = enabled === true; + this.logging.debug = debug === true; + }; + /** * Returns the maximum length of the instruction queue. * @memberOf THREE.LoaderSupport.WorkerDirector @@ -1592,6 +1294,16 @@ THREE.LoaderSupport.WorkerDirector = (function () { this.crossOrigin = crossOrigin; }; + /** + * Forces all ArrayBuffers to be transferred to worker to be copied. + * @memberOf THREE.LoaderSupport.WorkerDirector + * + * @param {boolean} forceWorkerDataCopy True or false. + */ + WorkerDirector.prototype.setForceWorkerDataCopy = function ( forceWorkerDataCopy ) { + this.workerDescription.forceWorkerDataCopy = forceWorkerDataCopy === true; + }; + /** * Create or destroy workers according limits. Set the name and register callbacks for dynamically created web workers. * @memberOf THREE.LoaderSupport.WorkerDirector @@ -1611,11 +1323,14 @@ THREE.LoaderSupport.WorkerDirector = (function () { for ( var instanceNo = 0; instanceNo < this.maxWebWorkers; instanceNo++ ) { + var workerSupport = new THREE.LoaderSupport.WorkerSupport(); + workerSupport.setLogging( this.logging.enabled, this.logging.debug ); + workerSupport.setForceWorkerDataCopy( this.workerDescription.forceWorkerDataCopy ); this.workerDescription.workerSupports[ instanceNo ] = { instanceNo: instanceNo, inUse: false, terminateRequested: false, - workerSupport: new THREE.LoaderSupport.WorkerSupport( this.logger ), + workerSupport: workerSupport, loader: null }; @@ -1684,7 +1399,7 @@ THREE.LoaderSupport.WorkerDirector = (function () { supportDesc.inUse = true; supportDesc.workerSupport.setTerminateRequested( supportDesc.terminateRequested ); - this.logger.logInfo( '\nAssigning next item from queue to worker (queue length: ' + this.instructionQueue.length + ')\n\n' ); + if ( this.logging.enabled ) console.info( '\nAssigning next item from queue to worker (queue length: ' + this.instructionQueue.length + ')\n\n' ); var scope = this; var prepDataCallbacks = prepData.getCallbacks(); @@ -1722,7 +1437,7 @@ THREE.LoaderSupport.WorkerDirector = (function () { WorkerDirector.prototype._buildLoader = function ( instanceNo ) { var classDef = this.workerDescription.classDef; var loader = Object.create( classDef.prototype ); - this.workerDescription.classDef.call( loader, THREE.DefaultLoadingManager, this.logger ); + classDef.call( loader, THREE.DefaultLoadingManager ); // verify that all required functions are implemented if ( ! loader.hasOwnProperty( 'instanceNo' ) ) throw classDef.name + ' has no property "instanceNo".'; @@ -1736,10 +1451,11 @@ THREE.LoaderSupport.WorkerDirector = (function () { if ( typeof loader.run !== 'function' ) throw classDef.name + ' has no function "run".'; if ( ! loader.hasOwnProperty( 'callbacks' ) || ! Validator.isValid( loader.callbacks ) ) { - this.logger.logWarn( classDef.name + ' has an invalid property "callbacks". Will change to "THREE.LoaderSupport.Callbacks"' ); + console.warn( classDef.name + ' has an invalid property "callbacks". Will change to "THREE.LoaderSupport.Callbacks"' ); loader.callbacks = new THREE.LoaderSupport.Callbacks(); } + return loader; }; @@ -1747,7 +1463,7 @@ THREE.LoaderSupport.WorkerDirector = (function () { if ( Validator.isValid( supportDesc ) ) { supportDesc.workerSupport.setTerminateRequested( true ); - this.logger.logInfo( 'Requested termination of worker #' + supportDesc.instanceNo + '.' ); + if ( this.logging.enabled ) console.info( 'Requested termination of worker #' + supportDesc.instanceNo + '.' ); var loaderCallbacks = supportDesc.loader.callbacks; if ( Validator.isValid( loaderCallbacks.onProgress ) ) loaderCallbacks.onProgress( { detail: { text: '' } } ); @@ -1763,7 +1479,7 @@ THREE.LoaderSupport.WorkerDirector = (function () { * @param {callback} callbackOnFinishedProcessing Function called once all workers finished processing. */ WorkerDirector.prototype.tearDown = function ( callbackOnFinishedProcessing ) { - this.logger.logInfo( 'WorkerDirector received the deregister call. Terminating all workers!' ); + if ( this.logging.enabled ) console.info( 'WorkerDirector received the deregister call. Terminating all workers!' ); this.instructionQueuePointer = this.instructionQueue.length; this.callbackOnFinishedProcessing = Validator.verifyInput( callbackOnFinishedProcessing, null ); diff --git a/examples/js/loaders/OBJLoader2.js b/examples/js/loaders/OBJLoader2.js index 03fd9e5fc4..4518715ed1 100644 --- a/examples/js/loaders/OBJLoader2.js +++ b/examples/js/loaders/OBJLoader2.js @@ -14,26 +14,108 @@ if ( THREE.LoaderSupport === undefined ) console.error( '"THREE.LoaderSupport" i * @class * * @param {THREE.DefaultLoadingManager} [manager] The loadingManager for the loader to use. Default is {@link THREE.DefaultLoadingManager} - * @param {THREE.LoaderSupport.ConsoleLogger} logger logger to be used */ THREE.OBJLoader2 = (function () { - var OBJLOADER2_VERSION = '2.3.1'; + var OBJLOADER2_VERSION = '2.4.0'; var Validator = THREE.LoaderSupport.Validator; - OBJLoader2.prototype = Object.create( THREE.LoaderSupport.LoaderBase.prototype ); - OBJLoader2.prototype.constructor = OBJLoader2; + function OBJLoader2( manager ) { + console.info( 'Using THREE.OBJLoader2 version: ' + OBJLOADER2_VERSION ); - function OBJLoader2( manager, logger ) { - THREE.LoaderSupport.LoaderBase.call( this, manager, logger ); - this.logger.logInfo( 'Using THREE.OBJLoader2 version: ' + OBJLOADER2_VERSION ); + this.manager = Validator.verifyInput( manager, THREE.DefaultLoadingManager ); + this.logging = { + enabled: true, + debug: false + }; + this.modelName = ''; + this.instanceNo = 0; + this.path = ''; + this.useIndices = false; + this.disregardNormals = false; this.materialPerSmoothingGroup = false; + this.loaderRootNode = new THREE.Group(); - this.workerSupport = null; + this.meshBuilder = new THREE.LoaderSupport.MeshBuilder(); + this.callbacks = new THREE.LoaderSupport.Callbacks(); + this.workerSupport = new THREE.LoaderSupport.WorkerSupport(); this.terminateWorkerOnLoad = true; } + /** + * Enable or disable logging in general (except warn and error), plus enable or disable debug logging. + * @memberOf THREE.OBJLoader2 + * + * @param {boolean} enabled True or false. + * @param {boolean} debug True or false. + */ + OBJLoader2.prototype.setLogging = function ( enabled, debug ) { + this.logging.enabled = enabled === true; + this.logging.debug = debug === true; + this.meshBuilder.setLogging( this.logging.enabled, this.logging.debug ); + }; + + /** + * Set the name of the model. + * @memberOf THREE.OBJLoader2 + * + * @param {string} modelName + */ + OBJLoader2.prototype.setModelName = function ( modelName ) { + this.modelName = Validator.verifyInput( modelName, this.modelName ); + }; + + /** + * The URL of the base path. + * @memberOf THREE.OBJLoader2 + * + * @param {string} path URL + */ + OBJLoader2.prototype.setPath = function ( path ) { + this.path = Validator.verifyInput( path, this.path ); + }; + + /** + * Set the node where the loaded objects will be attached directly. + * @memberOf THREE.OBJLoader2 + * + * @param {THREE.Object3D} streamMeshesTo Object already attached to scenegraph where new meshes will be attached to + */ + OBJLoader2.prototype.setStreamMeshesTo = function ( streamMeshesTo ) { + this.loaderRootNode = Validator.verifyInput( streamMeshesTo, this.loaderRootNode ); + }; + + /** + * Set materials loaded by MTLLoader or any other supplier of an Array of {@link THREE.Material}. + * @memberOf THREE.OBJLoader2 + * + * @param {THREE.Material[]} materials Array of {@link THREE.Material} + */ + OBJLoader2.prototype.setMaterials = function ( materials ) { + this.meshBuilder.setMaterials( materials ); + }; + + /** + * Instructs loaders to create indexed {@link THREE.BufferGeometry}. + * @memberOf THREE.OBJLoader2 + * + * @param {boolean} useIndices=false + */ + OBJLoader2.prototype.setUseIndices = function ( useIndices ) { + this.useIndices = useIndices === true; + }; + + /** + * Tells whether normals should be completely disregarded and regenerated. + * @memberOf THREE.OBJLoader2 + * + * @param {boolean} disregardNormals=false + */ + OBJLoader2.prototype.setDisregardNormals = function ( disregardNormals ) { + this.disregardNormals = disregardNormals === true; + }; + /** * Tells whether a material shall be created per smoothing group. * @memberOf THREE.OBJLoader2 @@ -44,6 +126,134 @@ THREE.OBJLoader2 = (function () { this.materialPerSmoothingGroup = materialPerSmoothingGroup === true; }; + OBJLoader2.prototype._setCallbacks = function ( callbacks ) { + if ( Validator.isValid( callbacks.onProgress ) ) this.callbacks.setCallbackOnProgress( callbacks.onProgress ); + if ( Validator.isValid( callbacks.onMeshAlter ) ) this.callbacks.setCallbackOnMeshAlter( callbacks.onMeshAlter ); + if ( Validator.isValid( callbacks.onLoad ) ) this.callbacks.setCallbackOnLoad( callbacks.onLoad ); + if ( Validator.isValid( callbacks.onLoadMaterials ) ) this.callbacks.setCallbackOnLoadMaterials( callbacks.onLoadMaterials ); + + this.meshBuilder._setCallbacks( this.callbacks ); + }; + + /** + * Announce feedback which is give to the registered callbacks. + * @memberOf THREE.OBJLoader2 + * @private + * + * @param {string} type The type of event + * @param {string} text Textual description of the event + * @param {number} numericalValue Numerical value describing the progress + */ + OBJLoader2.prototype.onProgress = function ( type, text, numericalValue ) { + var content = Validator.isValid( text ) ? text: ''; + var event = { + detail: { + type: type, + modelName: this.modelName, + instanceNo: this.instanceNo, + text: content, + numericalValue: numericalValue + } + }; + + if ( Validator.isValid( this.callbacks.onProgress ) ) this.callbacks.onProgress( event ); + + if ( this.logging.enabled && this.logging.debug ) console.debug( content ); + }; + + OBJLoader2.prototype._onError = function ( event ) { + var output = 'Error occurred while downloading!'; + + if ( event.currentTarget && event.currentTarget.statusText !== null ) { + + output += '\nurl: ' + event.currentTarget.responseURL + '\nstatus: ' + event.currentTarget.statusText; + + } + this.onProgress( 'error', output, -1 ); + throw output; + }; + + /** + * Use this convenient method to load a file at the given URL. By default the fileLoader uses an ArrayBuffer. + * @memberOf THREE.OBJLoader2 + * + * @param {string} url A string containing the path/URL of the file to be loaded. + * @param {callback} onLoad A function to be called after loading is successfully completed. The function receives loaded Object3D as an argument. + * @param {callback} [onProgress] A function to be called while the loading is in progress. The argument will be the XMLHttpRequest instance, which contains total and Integer bytes. + * @param {callback} [onError] A function to be called if an error occurs during loading. The function receives the error as an argument. + * @param {callback} [onMeshAlter] A function to be called after a new mesh raw data becomes available for alteration. + * @param {boolean} [useAsync] If true, uses async loading with worker, if false loads data synchronously. + */ + OBJLoader2.prototype.load = function ( url, onLoad, onProgress, onError, onMeshAlter, useAsync ) { + var resource = new THREE.LoaderSupport.ResourceDescriptor( url, 'OBJ' ); + this._loadObj( resource, onLoad, onProgress, onError, onMeshAlter, useAsync ); + }; + + OBJLoader2.prototype._loadObj = function ( resource, onLoad, onProgress, onError, onMeshAlter, useAsync ) { + if ( ! Validator.isValid( onError ) ) onError = this._onError; + + // fast-fail + if ( ! Validator.isValid( resource ) ) onError( 'An invalid ResourceDescriptor was provided. Unable to continue!' ); + var scope = this; + var fileLoaderOnLoad = function ( content ) { + + resource.content = content; + if ( useAsync ) { + + scope.parseAsync( content, onLoad ); + + } else { + + var callbacks = new THREE.LoaderSupport.Callbacks(); + callbacks.setCallbackOnMeshAlter( onMeshAlter ); + scope._setCallbacks( callbacks ); + onLoad( + { + detail: { + loaderRootNode: scope.parse( content ), + modelName: scope.modelName, + instanceNo: scope.instanceNo + } + } + ); + + } + }; + + // fast-fail + if ( ! Validator.isValid( resource.url ) || Validator.isValid( resource.content ) ) { + + fileLoaderOnLoad( Validator.isValid( resource.content ) ? resource.content : null ); + + } else { + + if ( ! Validator.isValid( onProgress ) ) { + var numericalValueRef = 0; + var numericalValue = 0; + onProgress = function ( event ) { + if ( ! event.lengthComputable ) return; + + numericalValue = event.loaded / event.total; + if ( numericalValue > numericalValueRef ) { + + numericalValueRef = numericalValue; + var output = 'Download of "' + resource.url + '": ' + ( numericalValue * 100 ).toFixed( 2 ) + '%'; + scope.onProgress( 'progressLoad', output, numericalValue ); + + } + }; + } + + + var fileLoader = new THREE.FileLoader( this.manager ); + fileLoader.setPath( this.path ); + fileLoader.setResponseType( 'arraybuffer' ); + fileLoader.load( resource.url, fileLoaderOnLoad, onProgress, onError ); + + } + }; + + /** * Run the loader according the provided instructions. * @memberOf THREE.OBJLoader2 @@ -53,9 +263,9 @@ THREE.OBJLoader2 = (function () { */ OBJLoader2.prototype.run = function ( prepData, workerSupportExternal ) { this._applyPrepData( prepData ); - var available = this.checkResourceDescriptorFiles( prepData.resources, + var available = prepData.checkResourceDescriptorFiles( prepData.resources, [ - { ext: "obj", type: "Uint8Array", ignore: false }, + { ext: "obj", type: "ArrayBuffer", ignore: false }, { ext: "mtl", type: "String", ignore: false }, { ext: "zip", type: "String", ignore: true } ] @@ -64,42 +274,32 @@ THREE.OBJLoader2 = (function () { this.terminateWorkerOnLoad = false; this.workerSupport = workerSupportExternal; - this.logger = workerSupportExternal.logger; + this.logging.enabled = this.workerSupport.logging.enabled; + this.logging.debug = this.workerSupport.logging.debug; } var scope = this; var onMaterialsLoaded = function ( materials ) { - scope.builder.setMaterials( materials ); + if ( materials !== null ) scope.meshBuilder.setMaterials( materials ); + scope._loadObj( available.obj, scope.callbacks.onLoad, null, null, scope.callbacks.onMeshAlter, prepData.useAsync ); - if ( Validator.isValid( available.obj.content ) ) { - - if ( prepData.useAsync ) { - - scope.parseAsync( available.obj.content, scope.callbacks.onLoad ); - - } else { - - scope.parse( available.obj.content ); - - } - } else { - - scope.setPath( available.obj.path ); - scope.load( available.obj.name, scope.callbacks.onLoad, null, null, scope.callbacks.onMeshAlter, prepData.useAsync ); - - } }; - - this._loadMtl( available.mtl, onMaterialsLoaded, prepData.crossOrigin ); + this._loadMtl( available.mtl, onMaterialsLoaded, prepData.crossOrigin, prepData.materialOptions ); }; OBJLoader2.prototype._applyPrepData = function ( prepData ) { - THREE.LoaderSupport.LoaderBase.prototype._applyPrepData.call( this, prepData ); - if ( Validator.isValid( prepData ) ) { + this.setLogging( prepData.logging.enabled, prepData.logging.debug ); + this.setModelName( prepData.modelName ); + this.setStreamMeshesTo( prepData.streamMeshesTo ); + this.meshBuilder.setMaterials( prepData.materials ); + this.setUseIndices( prepData.useIndices ); + this.setDisregardNormals( prepData.disregardNormals ); this.setMaterialPerSmoothingGroup( prepData.materialPerSmoothingGroup ); + this._setCallbacks( prepData.getCallbacks() ); + } }; @@ -110,26 +310,34 @@ THREE.OBJLoader2 = (function () { * @param {arraybuffer|string} content OBJ data as Uint8Array or String */ OBJLoader2.prototype.parse = function ( content ) { - this.logger.logTimeStart( 'OBJLoader2 parse: ' + this.modelName ); + // fast-fail in case of illegal data + if ( ! Validator.isValid( content ) ) { + + console.warn( 'Provided content is not a valid ArrayBuffer or String.' ); + return this.loaderRootNode; + + } + if ( this.logging.enabled ) console.time( 'OBJLoader2 parse: ' + this.modelName ); + this.meshBuilder.init(); var parser = new Parser(); - parser.setLogConfig( this.logger.enabled, this.logger.debug ); + parser.setLogging( this.logging.enabled, this.logging.debug ); parser.setMaterialPerSmoothingGroup( this.materialPerSmoothingGroup ); parser.setUseIndices( this.useIndices ); parser.setDisregardNormals( this.disregardNormals ); // sync code works directly on the material references - parser.setMaterials( this.builder.getMaterials() ); + parser.setMaterials( this.meshBuilder.getMaterials() ); var scope = this; var onMeshLoaded = function ( payload ) { - var meshes = scope.builder.processPayload( payload ); + var meshes = scope.meshBuilder.processPayload( payload ); var mesh; for ( var i in meshes ) { mesh = meshes[ i ]; scope.loaderRootNode.add( mesh ); } }; - parser.setCallbackBuilder( onMeshLoaded ); + parser.setCallbackMeshBuilder( onMeshLoaded ); var onProgressScoped = function ( text, numericalValue ) { scope.onProgress( 'progressParse', text, numericalValue ); }; @@ -137,12 +345,12 @@ THREE.OBJLoader2 = (function () { if ( content instanceof ArrayBuffer || content instanceof Uint8Array ) { - this.logger.logInfo( 'Parsing arrayBuffer...' ); + if ( this.logging.enabled ) console.info( 'Parsing arrayBuffer...' ); parser.parse( content ); } else if ( typeof( content ) === 'string' || content instanceof String ) { - this.logger.logInfo( 'Parsing text...' ); + if ( this.logging.enabled ) console.info( 'Parsing text...' ); parser.parseText( content ); } else { @@ -150,7 +358,7 @@ THREE.OBJLoader2 = (function () { throw 'Provided content was neither of type String nor Uint8Array! Aborting...'; } - this.logger.logTimeEnd( 'OBJLoader2 parse: ' + this.modelName ); + if ( this.logging.enabled ) console.timeEnd( 'OBJLoader2 parse: ' + this.modelName ); return this.loaderRootNode; }; @@ -163,9 +371,8 @@ THREE.OBJLoader2 = (function () { * @param {callback} onLoad Called after worker successfully completed loading */ OBJLoader2.prototype.parseAsync = function ( content, onLoad ) { - this.logger.logTimeStart( 'OBJLoader2 parseAsync: ' + this.modelName ); - var scope = this; + var measureTime = false; var scopedOnLoad = function () { onLoad( { @@ -176,18 +383,30 @@ THREE.OBJLoader2 = (function () { } } ); - scope.logger.logTimeEnd( 'OBJLoader2 parseAsync: ' + scope.modelName ); + if ( measureTime && scope.logging.enabled ) console.timeEnd( 'OBJLoader2 parseAsync: ' + scope.modelName ); }; + // fast-fail in case of illegal data + if ( ! Validator.isValid( content ) ) { + + console.warn( 'Provided content is not a valid ArrayBuffer.' ); + scopedOnLoad() + + } else { + + measureTime = true; + + } + if ( measureTime && this.logging.enabled ) console.time( 'OBJLoader2 parseAsync: ' + this.modelName ); + this.meshBuilder.init(); + var scopedOnMeshLoaded = function ( payload ) { - var meshes = scope.builder.processPayload( payload ); + var meshes = scope.meshBuilder.processPayload( payload ); var mesh; for ( var i in meshes ) { mesh = meshes[ i ]; scope.loaderRootNode.add( mesh ); } }; - - this.workerSupport = Validator.verifyInput( this.workerSupport, new THREE.LoaderSupport.WorkerSupport( this.logger ) ); var buildCode = function ( funcBuildObject, funcBuildSingleton ) { var workerCode = ''; workerCode += '/**\n'; @@ -195,8 +414,6 @@ THREE.OBJLoader2 = (function () { workerCode += ' */\n\n'; workerCode += 'THREE = { LoaderSupport: {} };\n\n'; workerCode += funcBuildObject( 'THREE.LoaderSupport.Validator', Validator ); - workerCode += funcBuildSingleton( 'THREE.LoaderSupport.ConsoleLogger', THREE.LoaderSupport.ConsoleLogger ); - workerCode += funcBuildSingleton( 'THREE.LoaderSupport.LoaderBase', THREE.LoaderSupport.LoaderBase ); workerCode += funcBuildSingleton( 'Parser', Parser ); return workerCode; @@ -206,7 +423,7 @@ THREE.OBJLoader2 = (function () { if ( scope.terminateWorkerOnLoad ) this.workerSupport.setTerminateRequested( true ); var materialNames = {}; - var materials = this.builder.getMaterials(); + var materials = this.meshBuilder.getMaterials(); for ( var materialName in materials ) { materialNames[ materialName ] = materialName; @@ -220,9 +437,9 @@ THREE.OBJLoader2 = (function () { useIndices: this.useIndices, disregardNormals: this.disregardNormals }, - logger: { - debug: this.logger.debug, - enabled: this.logger.enabled + logging: { + enabled: this.logging.enabled, + debug: this.logging.debug }, materials: { // in async case only material names are supplied to parser @@ -245,7 +462,9 @@ THREE.OBJLoader2 = (function () { function Parser() { this.callbackProgress = null; - this.callbackBuilder = null; + this.callbackMeshBuilder = null; + this.contentRef = null; + this.legacyMode = false; this.materials = {}; this.useAsync = false; @@ -287,10 +506,15 @@ THREE.OBJLoader2 = (function () { vertices: 0, faces: 0, doubleIndicesCount: 0, + lineByte: 0, currentByte: 0, totalBytes: 0 }; - this.logger = new THREE.LoaderSupport.ConsoleLogger(); + + this.logging = { + enabled: true, + debug: false + }; } Parser.prototype.resetRawMesh = function () { @@ -330,24 +554,24 @@ THREE.OBJLoader2 = (function () { this.materials = THREE.LoaderSupport.Validator.verifyInput( this.materials, {} ); }; - Parser.prototype.setCallbackBuilder = function ( callbackBuilder ) { - if ( ! THREE.LoaderSupport.Validator.isValid( callbackBuilder ) ) throw 'Unable to run as no "builder" callback is set.'; - this.callbackBuilder = callbackBuilder; + Parser.prototype.setCallbackMeshBuilder = function ( callbackMeshBuilder ) { + if ( ! THREE.LoaderSupport.Validator.isValid( callbackMeshBuilder ) ) throw 'Unable to run as no "MeshBuilder" callback is set.'; + this.callbackMeshBuilder = callbackMeshBuilder; }; Parser.prototype.setCallbackProgress = function ( callbackProgress ) { this.callbackProgress = callbackProgress; }; - Parser.prototype.setLogConfig = function ( enabled, debug ) { - this.logger.setEnabled( enabled ); - this.logger.setDebug( debug ); + Parser.prototype.setLogging = function ( enabled, debug ) { + this.logging.enabled = enabled === true; + this.logging.debug = debug === true; }; Parser.prototype.configure = function () { this.pushSmoothingGroup( 1 ); - if ( this.logger.isEnabled() ) { + if ( this.logging.enabled ) { var matKeys = Object.keys( this.materials ); var matNames = ( matKeys.length > 0 ) ? '\n\tmaterialNames:\n\t\t- ' + matKeys.join( '\n\t\t- ' ) : '\n\tmaterialNames: None'; @@ -357,9 +581,9 @@ THREE.OBJLoader2 = (function () { + '\n\tmaterialPerSmoothingGroup: ' + this.materialPerSmoothingGroup + '\n\tuseIndices: ' + this.useIndices + '\n\tdisregardNormals: ' + this.disregardNormals - + '\n\tcallbackBuilderName: ' + this.callbackBuilder.name + + '\n\tcallbackMeshBuilderName: ' + this.callbackMeshBuilder.name + '\n\tcallbackProgressName: ' + this.callbackProgress.name; - this.logger.logInfo( printedConfig ); + console.info( printedConfig ); } }; @@ -370,33 +594,28 @@ THREE.OBJLoader2 = (function () { * @param {Uint8Array} arrayBuffer OBJ data as Uint8Array */ Parser.prototype.parse = function ( arrayBuffer ) { - this.logger.logTimeStart( 'OBJLoader2.Parser.parse' ); + if ( this.logging.enabled ) console.time( 'OBJLoader2.Parser.parse' ); this.configure(); var arrayBufferView = new Uint8Array( arrayBuffer ); + this.contentRef = arrayBufferView; var length = arrayBufferView.byteLength; this.globalCounts.totalBytes = length; var buffer = new Array( 128 ); - var bufferPointer = 0; - var slashSpacePattern = new Array( 16 ); - var slashSpacePatternPointer = 0; - var code; - var word = ''; - var i = 0; - for ( ; i < length; i++ ) { + + for ( var code, word = '', bufferPointer = 0, slashesCount = 0, i = 0; i < length; i++ ) { code = arrayBufferView[ i ]; switch ( code ) { // space case 32: if ( word.length > 0 ) buffer[ bufferPointer++ ] = word; - slashSpacePattern[ slashSpacePatternPointer++ ] = 0; word = ''; break; // slash case 47: if ( word.length > 0 ) buffer[ bufferPointer++ ] = word; - slashSpacePattern[ slashSpacePatternPointer++ ] = 1; + slashesCount++; word = ''; break; @@ -404,10 +623,11 @@ THREE.OBJLoader2 = (function () { case 10: if ( word.length > 0 ) buffer[ bufferPointer++ ] = word; word = ''; + this.globalCounts.lineByte = this.globalCounts.currentByte; this.globalCounts.currentByte = i; - this.processLine( buffer, bufferPointer, slashSpacePattern, slashSpacePatternPointer ); + this.processLine( buffer, bufferPointer, slashesCount ); bufferPointer = 0; - slashSpacePatternPointer = 0; + slashesCount = 0; break; // CR @@ -420,7 +640,7 @@ THREE.OBJLoader2 = (function () { } } this.finalizeParsing(); - this.logger.logTimeEnd( 'OBJLoader2.Parser.parse' ); + if ( this.logging.enabled ) console.timeEnd( 'OBJLoader2.Parser.parse' ); }; /** @@ -430,41 +650,37 @@ THREE.OBJLoader2 = (function () { * @param {string} text OBJ data as string */ Parser.prototype.parseText = function ( text ) { - this.logger.logTimeStart( 'OBJLoader2.Parser.parseText' ); + if ( this.logging.enabled ) console.time( 'OBJLoader2.Parser.parseText' ); this.configure(); - + this.legacyMode = true; + this.contentRef = text; var length = text.length; this.globalCounts.totalBytes = length; var buffer = new Array( 128 ); - var bufferPointer = 0; - var slashSpacePattern = new Array( 16 ); - var slashSpacePatternPointer = 0; - var char; - var word = ''; - var i = 0; - for ( ; i < length; i++ ) { + + for ( var char, word = '', bufferPointer = 0, slashesCount = 0, i = 0; i < length; i++ ) { char = text[ i ]; switch ( char ) { case ' ': if ( word.length > 0 ) buffer[ bufferPointer++ ] = word; - slashSpacePattern[ slashSpacePatternPointer++ ] = 0; word = ''; break; case '/': if ( word.length > 0 ) buffer[ bufferPointer++ ] = word; - slashSpacePattern[ slashSpacePatternPointer++ ] = 1; + slashesCount++; word = ''; break; case '\n': if ( word.length > 0 ) buffer[ bufferPointer++ ] = word; word = ''; + this.globalCounts.lineByte = this.globalCounts.currentByte; this.globalCounts.currentByte = i; - this.processLine( buffer, bufferPointer, slashSpacePattern, slashSpacePatternPointer ); + this.processLine( buffer, bufferPointer, slashesCount ); bufferPointer = 0; - slashSpacePatternPointer = 0; + slashesCount = 0; break; case '\r': @@ -475,47 +691,36 @@ THREE.OBJLoader2 = (function () { } } this.finalizeParsing(); - this.logger.logTimeEnd( 'OBJLoader2.Parser.parseText' ); + if ( this.logging.enabled ) console.timeEnd( 'OBJLoader2.Parser.parseText' ); }; - Parser.prototype.processLine = function ( buffer, bufferPointer, slashSpacePattern, slashSpacePatternPointer ) { + Parser.prototype.processLine = function ( buffer, bufferPointer, slashesCount ) { if ( bufferPointer < 1 ) return; - var countSlashes = function ( slashSpacePattern, slashSpacePatternPointer ) { - var slashesCount = 0; - for ( var i = 0; i < slashSpacePatternPointer; i++ ) { - slashesCount += slashSpacePattern[ i ]; - } - return slashesCount; - }; + var reconstructString = function ( content, legacyMode, start, stop ) { + var line = ''; + if ( stop > start ) { - var concatStringBuffer = function ( buffer, bufferPointer, slashSpacePattern ) { - var concatBuffer = ''; - if ( bufferPointer === 2 ) { + var i; + if ( legacyMode ) { - concatBuffer = buffer[ 1 ]; + for ( i = start; i < stop; i++ ) line += content[ i ]; - } else { + } else { - var bufferLength = bufferPointer - 1; - for ( var i = 1; i < bufferLength; i++ ) { - concatBuffer += buffer[ i ] + ( slashSpacePattern[ i ] === 0 ? ' ' : '/' ); + for ( i = start; i < stop; i++ ) line += String.fromCharCode( content[ i ] ); } - concatBuffer += buffer[ bufferLength ]; - - } - return concatBuffer; - }; + line = line.trim(); - var flushStringBuffer = function ( buffer, bufferPointer ) { - for ( var i = 0; i < bufferPointer; i++ ) { - buffer[ i ] = ''; } + return line; }; - switch ( buffer[ 0 ] ) { + var bufferLength, length, i, lineDesignation; + lineDesignation = buffer [ 0 ]; + switch ( lineDesignation ) { case 'v': this.vertices.push( parseFloat( buffer[ 1 ] ) ); this.vertices.push( parseFloat( buffer[ 2 ] ) ); @@ -541,76 +746,103 @@ THREE.OBJLoader2 = (function () { break; case 'f': - var slashesCount = countSlashes( slashSpacePattern, slashSpacePatternPointer ); - var bufferLength = bufferPointer - 1; + bufferLength = bufferPointer - 1; // "f vertex ..." if ( slashesCount === 0 ) { this.checkFaceType( 0 ); + for ( i = 2, length = bufferLength; i < length; i ++ ) { - // "f vertex/uv ..." + this.buildFace( buffer[ 1 ] ); + this.buildFace( buffer[ i ] ); + this.buildFace( buffer[ i + 1 ] ); + + } + + // "f vertex/uv ..." } else if ( bufferLength === slashesCount * 2 ) { this.checkFaceType( 1 ); + for ( i = 3, length = bufferLength - 2; i < length; i += 2 ) { + + this.buildFace( buffer[ 1 ], buffer[ 2 ] ); + this.buildFace( buffer[ i ], buffer[ i + 1 ] ); + this.buildFace( buffer[ i + 2 ], buffer[ i + 3 ] ); + + } - // "f vertex/uv/normal ..." + // "f vertex/uv/normal ..." } else if ( bufferLength * 2 === slashesCount * 3 ) { this.checkFaceType( 2 ); + for ( i = 4, length = bufferLength - 3; i < length; i += 3 ) { - // "f vertex//normal ..." + this.buildFace( buffer[ 1 ], buffer[ 2 ], buffer[ 3 ] ); + this.buildFace( buffer[ i ], buffer[ i + 1 ], buffer[ i + 2 ] ); + this.buildFace( buffer[ i + 3 ], buffer[ i + 4 ], buffer[ i + 5 ] ); + + } + + // "f vertex//normal ..." } else { this.checkFaceType( 3 ); + for ( i = 3, length = bufferLength - 2; i < length; i += 2 ) { + + this.buildFace( buffer[ 1 ], undefined, buffer[ 2 ] ); + this.buildFace( buffer[ i ], undefined, buffer[ i + 1 ] ); + this.buildFace( buffer[ i + 2 ], undefined, buffer[ i + 3 ] ); + + } } - this.processFaces( buffer, bufferLength ); break; case 'l': - this.checkFaceType( 4 ); - this.processLinesOrPoints( buffer, bufferPointer, countSlashes( slashSpacePattern, slashSpacePatternPointer ) ); - break; - case 'p': - this.checkFaceType( 5 ); - this.processLinesOrPoints( buffer, bufferPointer, 0 ); + bufferLength = bufferPointer - 1; + if ( bufferLength === slashesCount * 2 ) { + + this.checkFaceType( 4 ); + for ( i = 1, length = bufferLength + 1; i < length; i += 2 ) this.buildFace( buffer[ i ], buffer[ i + 1 ] ); + + } else { + + this.checkFaceType( ( lineDesignation === 'l' ) ? 5 : 6 ); + for ( i = 1, length = bufferLength + 1; i < length; i ++ ) this.buildFace( buffer[ i ] ); + + } break; case 's': this.pushSmoothingGroup( buffer[ 1 ] ); - flushStringBuffer( buffer, bufferPointer ); break; case 'g': // 'g' leads to creation of mesh if valid data (faces declaration was done before), otherwise only groupName gets set this.processCompletedMesh(); - this.rawMesh.groupName = THREE.LoaderSupport.Validator.verifyInput( concatStringBuffer( buffer, bufferPointer, slashSpacePattern ), '' ); - flushStringBuffer( buffer, bufferPointer ); + this.rawMesh.groupName = reconstructString( this.contentRef, this.legacyMode, this.globalCounts.lineByte + 2, this.globalCounts.currentByte ); break; case 'o': // 'o' is pure meta-information and does not result in creation of new meshes - this.rawMesh.objectName = THREE.LoaderSupport.Validator.verifyInput( concatStringBuffer( buffer, bufferPointer, slashSpacePattern ), '' ); - flushStringBuffer( buffer, bufferPointer ); + this.rawMesh.objectName = reconstructString( this.contentRef, this.legacyMode, this.globalCounts.lineByte + 2, this.globalCounts.currentByte ); break; case 'mtllib': - this.rawMesh.mtllibName = THREE.LoaderSupport.Validator.verifyInput( concatStringBuffer( buffer, bufferPointer, slashSpacePattern ), '' ); - flushStringBuffer( buffer, bufferPointer ); + this.rawMesh.mtllibName = reconstructString( this.contentRef, this.legacyMode, this.globalCounts.lineByte + 7, this.globalCounts.currentByte ); break; case 'usemtl': - var mtlName = concatStringBuffer( buffer, bufferPointer, slashSpacePattern ); - if ( this.rawMesh.activeMtlName !== mtlName && THREE.LoaderSupport.Validator.isValid( mtlName ) ) { + var mtlName = reconstructString( this.contentRef, this.legacyMode, this.globalCounts.lineByte + 7, this.globalCounts.currentByte ); + if ( mtlName !== '' && this.rawMesh.activeMtlName !== mtlName ) { this.rawMesh.activeMtlName = mtlName; this.rawMesh.counts.mtlCount++; this.checkSubGroup(); } - flushStringBuffer( buffer, bufferPointer ); break; default: @@ -643,7 +875,8 @@ THREE.OBJLoader2 = (function () { * faceType = 2: "f vertex/uv/normal ..." * faceType = 3: "f vertex//normal ..." * faceType = 4: "l vertex/uv ..." or "l vertex ..." - * faceType = 5: "p vertex ..." + * faceType = 5: "l vertex ..." + * faceType = 6: "p vertex ..." */ Parser.prototype.checkFaceType = function ( faceType ) { if ( this.rawMesh.faceType !== faceType ) { @@ -680,56 +913,6 @@ THREE.OBJLoader2 = (function () { } }; - Parser.prototype.processFaces = function ( buffer, bufferLength ) { - var i, length; - - // "f vertex ..." - if ( this.rawMesh.faceType === 0 ) { - - for ( i = 2, length = bufferLength; i < length; i ++ ) { - - this.buildFace( buffer[ 1 ] ); - this.buildFace( buffer[ i ] ); - this.buildFace( buffer[ i + 1 ] ); - - } - - // "f vertex/uv ..." - } else if ( this.rawMesh.faceType === 1 ) { - - for ( i = 3, length = bufferLength - 2; i < length; i += 2 ) { - - this.buildFace( buffer[ 1 ], buffer[ 2 ] ); - this.buildFace( buffer[ i ], buffer[ i + 1 ] ); - this.buildFace( buffer[ i + 2 ], buffer[ i + 3 ] ); - - } - - // "f vertex/uv/normal ..." - } else if ( this.rawMesh.faceType === 2 ) { - - for ( i = 4, length = bufferLength - 3; i < length; i += 3 ) { - - this.buildFace( buffer[ 1 ], buffer[ 2 ], buffer[ 3 ] ); - this.buildFace( buffer[ i ], buffer[ i + 1 ], buffer[ i + 2 ] ); - this.buildFace( buffer[ i + 3 ], buffer[ i + 4 ], buffer[ i + 5 ] ); - - } - - // "f vertex//normal ..." - } else { - - for ( i = 3, length = bufferLength - 2; i < length; i += 2 ) { - - this.buildFace( buffer[ 1 ], undefined, buffer[ 2 ] ); - this.buildFace( buffer[ i ], undefined, buffer[ i + 1 ] ); - this.buildFace( buffer[ i + 2 ], undefined, buffer[ i + 3 ] ); - - } - - } - }; - Parser.prototype.buildFace = function ( faceIndexV, faceIndexU, faceIndexN ) { if ( this.disregardNormals ) faceIndexN = undefined; var scope = this; @@ -752,7 +935,6 @@ THREE.OBJLoader2 = (function () { colors.push( scope.colors[ indexPointerC ] ); } - if ( faceIndexU ) { var faceIndexUi = parseInt( faceIndexU ); @@ -800,29 +982,6 @@ THREE.OBJLoader2 = (function () { this.rawMesh.counts.faceCount++; }; - /* - * Support for lines with or without texture or Points (just Vertex). - * First element in indexArray is the line/point identification - * - * : "l vertex/uv vertex/uv ..." - * 1: "l vertex vertex ..." - */ - Parser.prototype.processLinesOrPoints = function ( buffer, bufferPointer, slashCount ) { - var i = 1; - var length; - var bufferLength = bufferPointer - 1; - - if ( bufferLength === slashCount * 2 ) { - - for ( length = bufferPointer; i < length; i += 2 ) this.buildFace( buffer[ i ], buffer[ i + 1 ] ); - - } else { - - for ( length = bufferPointer; i < length; i ++ ) this.buildFace( buffer[ i ] ); - - } - }; - Parser.prototype.createRawMeshReport = function ( inputObjectCount ) { return 'Input Object number: ' + inputObjectCount + '\n\tObject name: ' + this.rawMesh.objectName + @@ -900,7 +1059,7 @@ THREE.OBJLoader2 = (function () { throw 'Vertex Colors were detected, but vertex count and color count do not match!'; } - if ( this.logger.isDebug() ) this.logger.logDebug( this.createRawMeshReport( this.inputObjectCount ) ); + if ( this.logging.enabled && this.logging.debug ) console.debug( this.createRawMeshReport( this.inputObjectCount ) ); this.inputObjectCount++; this.buildMesh( result ); @@ -916,7 +1075,7 @@ THREE.OBJLoader2 = (function () { }; /** - * SubGroups are transformed to too intermediate format that is forwarded to the Builder. + * SubGroups are transformed to too intermediate format that is forwarded to the MeshBuilder. * It is ensured that SubGroups only contain objects with vertices (no need to check). * * @param result @@ -967,7 +1126,7 @@ THREE.OBJLoader2 = (function () { } else { - materialName = this.rawMesh.faceType === 4 ? 'defaultLineMaterial' : 'defaultPointMaterial'; + materialName = this.rawMesh.faceType === 6 ? 'defaultPointMaterial' : 'defaultLineMaterial'; } materialOrg = this.materials[ materialNameOrg ]; @@ -978,7 +1137,7 @@ THREE.OBJLoader2 = (function () { var defaultMaterialName = haveVertexColors ? 'defaultVertexColorMaterial' : 'defaultMaterial'; materialOrg = this.materials[ defaultMaterialName ]; - this.logger.logWarn( 'object_group "' + meshOutputGroup.objectName + '_' + + if ( this.logging.enabled ) console.warn( 'object_group "' + meshOutputGroup.objectName + '_' + meshOutputGroup.groupName + '" was defined with unresolvable material "' + materialNameOrg + '"! Assigning "' + defaultMaterialName + '".' ); materialNameOrg = defaultMaterialName; @@ -1008,7 +1167,7 @@ THREE.OBJLoader2 = (function () { materialCloneInstructions: materialCloneInstructions } }; - this.callbackBuilder( payload ); + this.callbackMeshBuilder( payload ); // fake entry for async; sync Parser always works on material references (Builder update directly visible here) if ( this.useAsync ) this.materials[ materialName ] = materialCloneInstructions; @@ -1072,7 +1231,7 @@ THREE.OBJLoader2 = (function () { } - if ( this.logger.isDebug() ) { + if ( this.logging.enabled && this.logging.debug ) { var materialIndexLine = THREE.LoaderSupport.Validator.isValid( selectedMaterialIndex ) ? '\n\t\tmaterialIndex: ' + selectedMaterialIndex : ''; var createdReport = '\tOutput Object no.: ' + this.outputObjectCount + '\n\t\tgroupName: ' + meshOutputGroup.groupName + @@ -1087,13 +1246,13 @@ THREE.OBJLoader2 = (function () { '\n\t\t#colors: ' + meshOutputGroup.colors.length / 3 + '\n\t\t#uvs: ' + meshOutputGroup.uvs.length / 2 + '\n\t\t#normals: ' + meshOutputGroup.normals.length / 3; - this.logger.logDebug( createdReport ); + console.debug( createdReport ); } } this.outputObjectCount++; - this.callbackBuilder( + this.callbackMeshBuilder( { cmd: 'meshData', progress: { @@ -1115,7 +1274,7 @@ THREE.OBJLoader2 = (function () { uvs: uvFA }, // 0: mesh, 1: line, 2: point - geometryType: this.rawMesh.faceType < 4 ? 0 : ( this.rawMesh.faceType === 4 ) ? 1 : 2 + geometryType: this.rawMesh.faceType < 4 ? 0 : ( this.rawMesh.faceType === 6 ) ? 2 : 1 }, [ vertexFA.buffer ], THREE.LoaderSupport.Validator.isValid( indexUA ) ? [ indexUA.buffer ] : null, @@ -1126,14 +1285,14 @@ THREE.OBJLoader2 = (function () { }; Parser.prototype.finalizeParsing = function () { - this.logger.logInfo( 'Global output object count: ' + this.outputObjectCount ); - if ( this.processCompletedMesh() && this.logger.isEnabled() ) { + if ( this.logging.enabled ) console.info( 'Global output object count: ' + this.outputObjectCount ); + if ( this.processCompletedMesh() && this.logging.enabled ) { var parserFinalReport = 'Overall counts: ' + '\n\tVertices: ' + this.globalCounts.vertices + '\n\tFaces: ' + this.globalCounts.faces + '\n\tMultiple definitions: ' + this.globalCounts.doubleIndicesCount; - this.logger.logInfo( parserFinalReport ); + console.info( parserFinalReport ); } }; @@ -1160,7 +1319,7 @@ THREE.OBJLoader2 = (function () { OBJLoader2.prototype._loadMtl = function ( resource, callbackOnLoad, crossOrigin, materialOptions ) { if ( THREE.MTLLoader === undefined ) console.error( '"THREE.MTLLoader" is not available. "THREE.OBJLoader2" requires it for loading MTL files.' ); - if ( Validator.isValid( resource ) ) this.logger.logTimeStart( 'Loading MTL: ' + resource.name ); + if ( Validator.isValid( resource ) && this.logging.enabled ) console.time( 'Loading MTL: ' + resource.name ); var materials = []; var scope = this; @@ -1180,15 +1339,10 @@ THREE.OBJLoader2 = (function () { } } - if ( Validator.isValid( resource ) ) scope.logger.logTimeEnd( 'Loading MTL: ' + resource.name ); + if ( Validator.isValid( resource ) && scope.logging.enabled ) console.timeEnd( 'Loading MTL: ' + resource.name ); callbackOnLoad( materials, materialCreator ); }; - var mtlLoader = new THREE.MTLLoader( this.manager ); - crossOrigin = Validator.verifyInput( crossOrigin, 'anonymous' ); - mtlLoader.setCrossOrigin( crossOrigin ); - if ( Validator.isValid( materialOptions ) ) mtlLoader.setMaterialOptions( materialOptions ); - // fast-fail if ( ! Validator.isValid( resource ) || ( ! Validator.isValid( resource.content ) && ! Validator.isValid( resource.url ) ) ) { @@ -1196,20 +1350,25 @@ THREE.OBJLoader2 = (function () { } else { + var mtlLoader = new THREE.MTLLoader( this.manager ); + crossOrigin = Validator.verifyInput( crossOrigin, 'anonymous' ); + mtlLoader.setCrossOrigin( crossOrigin ); mtlLoader.setPath( resource.path ); + if ( Validator.isValid( materialOptions ) ) mtlLoader.setMaterialOptions( materialOptions ); + if ( Validator.isValid( resource.content ) ) { processMaterials( Validator.isValid( resource.content ) ? mtlLoader.parse( resource.content ) : null ); } else if ( Validator.isValid( resource.url ) ) { - var onError = function ( event ) { - var output = 'Error occurred while downloading "' + resource.url + '"'; - scope.logger.logError( output, event instanceof ProgressEvent ? [ 'Status: ' + event.currentTarget.statusText ] : null ); - throw output; - }; + var fileLoader = new THREE.FileLoader( this.manager ); + fileLoader.load( resource.url, function ( text ) { + + resource.content = text; + processMaterials( mtlLoader.parse( text ) ); - mtlLoader.load( resource.name, processMaterials, undefined, onError ); + }, this._onProgress, this._onError ); } } diff --git a/examples/models/obj/verify/verify.html b/examples/models/obj/verify/verify.html index c97aa3fff8..a6eb15fcdf 100644 --- a/examples/models/obj/verify/verify.html +++ b/examples/models/obj/verify/verify.html @@ -160,14 +160,10 @@ objLoader2.setModelName( modelName ); objLoader2.setMaterials( materials ); - var mats = objLoader2.builder.getMaterials(); - var defaultPointMaterial = mats[ 'defaultPointMaterial' ]; - defaultPointMaterial.sizeAttenuation = true; - - objLoader2.getLogger().setDebug( true ); + objLoader2.setLogging( true, false ); objLoader2.load( './verify.obj', callbackOnLoad, null, null, null, false ); }; - objLoader2.loadMtl( './verify.mtl', null, onLoadMtl, null, { invertTrProperty: false } ); + objLoader2.loadMtl( './verify.mtl', null, onLoadMtl ); }; OBJLoaderVerify.prototype._reportProgress = function( event ) { diff --git a/examples/webgl_loader_obj2.html b/examples/webgl_loader_obj2.html index cca7721113..daf62615df 100644 --- a/examples/webgl_loader_obj2.html +++ b/examples/webgl_loader_obj2.html @@ -152,7 +152,7 @@ var onLoadMtl = function ( materials ) { objLoader.setModelName( modelName ); objLoader.setMaterials( materials ); - objLoader.getLogger().setDebug( true ); + objLoader.setLogging( true, true ); objLoader.load( 'models/obj/female02/female02.obj', callbackOnLoad, null, null, null, false ); }; objLoader.loadMtl( 'models/obj/female02/female02.mtl', null, onLoadMtl ); diff --git a/examples/webgl_loader_obj2_meshspray.html b/examples/webgl_loader_obj2_meshspray.html index 3f4b7c3e4d..424348d896 100644 --- a/examples/webgl_loader_obj2_meshspray.html +++ b/examples/webgl_loader_obj2_meshspray.html @@ -85,13 +85,35 @@ var MeshSpray = (function () { - MeshSpray.prototype = Object.create( THREE.LoaderSupport.LoaderBase.prototype ); - MeshSpray.prototype.constructor = MeshSpray; + var Validator = THREE.LoaderSupport.Validator; - function MeshSpray( manager, logger ) { - THREE.LoaderSupport.LoaderBase.call( this, manager, logger ); + function MeshSpray( manager ) { + this.manager = Validator.verifyInput( manager, THREE.DefaultLoadingManager ); + this.logging = { + enabled: true, + debug: false + }; + + this.instanceNo = 0; + this.loaderRootNode = new THREE.Group(); + + this.meshBuilder = new THREE.LoaderSupport.MeshBuilder(); + this.callbacks = new THREE.LoaderSupport.Callbacks(); this.workerSupport = null; - this.logger = new THREE.LoaderSupport.ConsoleLogger(); + } + + MeshSpray.prototype.setLogging = function ( enabled, debug ) { + this.logging.enabled = enabled === true; + this.logging.debug = debug === true; + this.meshBuilder.setLogging( this.logging.enabled, this.logging.debug ); + }; + + MeshSpray.prototype.setStreamMeshesTo = function ( streamMeshesTo ) { + this.loaderRootNode = Validator.verifyInput( streamMeshesTo, this.loaderRootNode ); + }; + + MeshSpray.prototype.setForceWorkerDataCopy = function ( forceWorkerDataCopy ) { + // nothing to do here }; MeshSpray.prototype.run = function ( prepData, workerSupportExternal ) { @@ -99,21 +121,23 @@ if ( THREE.LoaderSupport.Validator.isValid( workerSupportExternal ) ) { this.workerSupport = workerSupportExternal; - this.logger = workerSupportExternal.logger; + this.logging.enabled = this.workerSupport.logging.enabled; + this.logging.debug = this.workerSupport.logging.debug; } else { this.workerSupport = THREE.LoaderSupport.Validator.verifyInput( this.workerSupport, new THREE.LoaderSupport.WorkerSupport() ); } - - this.logger.logTimeStart( 'MeshSpray' ); + if ( this.logging.enabled ) console.time( 'MeshSpray' + this.instanceNo ); this._applyPrepData( prepData ); + this.meshBuilder.init(); + var scope = this; var scopeBuilderFunc = function ( payload ) { - var meshes = scope.builder.processPayload( payload ); + var meshes = scope.meshBuilder.processPayload( payload ); var mesh; for ( var i in meshes ) { mesh = meshes[ i ]; @@ -131,7 +155,7 @@ } } ); - scope.logger.logTimeEnd( 'MeshSpray' ); + if ( scope.logging.enabled ) console.timeEnd( 'MeshSpray' + scope.instanceNo ); }; var buildCode = function ( funcBuildObject, funcBuildSingleton ) { @@ -141,7 +165,6 @@ workerCode += ' */\n\n'; workerCode += 'THREE.LoaderSupport = {};\n\n'; workerCode += funcBuildObject( 'THREE.LoaderSupport.Validator', THREE.LoaderSupport.Validator ); - workerCode += funcBuildSingleton( 'THREE.LoaderSupport.ConsoleLogger', THREE.LoaderSupport.ConsoleLogger ); workerCode += funcBuildSingleton( 'Parser', Parser ); return workerCode; @@ -157,11 +180,11 @@ globalObjectCount: prepData.globalObjectCount }, materials: { - serializedMaterials: this.builder.getMaterialsJSON() + serializedMaterials: this.meshBuilder.getMaterialsJSON() }, - logger: { - debug: this.logger.debug, - enabled: this.logger.enabled + logging: { + enabled: this.logging.enabled, + debug: this.logging.debug }, data: { input: null, @@ -171,6 +194,28 @@ ); }; + MeshSpray.prototype._applyPrepData = function ( prepData ) { + if ( Validator.isValid( prepData ) ) { + + this.setLogging( prepData.logging.enabled, prepData.logging.debug ); + this.setStreamMeshesTo( prepData.streamMeshesTo ); + this.meshBuilder.setMaterials( prepData.materials ); + this._setCallbacks( prepData.getCallbacks() ); + + } + }; + + MeshSpray.prototype._setCallbacks = function ( callbacks ) { + if ( Validator.isValid( callbacks.onProgress ) ) this.callbacks.setCallbackOnProgress( callbacks.onProgress ); + if ( Validator.isValid( callbacks.onMeshAlter ) ) this.callbacks.setCallbackOnMeshAlter( callbacks.onMeshAlter ); + if ( Validator.isValid( callbacks.onLoad ) ) this.callbacks.setCallbackOnLoad( callbacks.onLoad ); + if ( Validator.isValid( callbacks.onLoadMaterials ) ) this.callbacks.setCallbackOnLoadMaterials( callbacks.onLoadMaterials ); + + this.meshBuilder._setCallbacks( this.callbacks ); + }; + + + var Parser = ( function () { function Parser() { @@ -180,15 +225,18 @@ this.debug = false; this.dimension = 200; this.quantity = 1; - this.callbackBuilder = null; + this.callbackMeshBuilder = null; this.callbackProgress = null; - this.logger = new THREE.LoaderSupport.ConsoleLogger(); this.serializedMaterials = null; + this.logging = { + enabled: true, + debug: false + }; }; - Parser.prototype.setLogConfig = function ( enabled, debug ) { - this.logger.setEnabled( enabled ); - this.logger.setDebug( debug ); + Parser.prototype.setLogging = function ( enabled, debug ) { + this.logging.enabled = enabled === true; + this.logging.debug = debug === true; }; Parser.prototype.parse = function () { @@ -277,10 +325,10 @@ serializedMaterials: newSerializedMaterials } }; - this.callbackBuilder( payload ); + this.callbackMeshBuilder( payload ); this.globalObjectCount++; - this.callbackBuilder( + this.callbackMeshBuilder( { cmd: 'meshData', progress: { @@ -307,7 +355,7 @@ uvFA !== null ? [ uvFA.buffer ] : null ); - this.logger.logInfo( 'Global output object count: ' + this.globalObjectCount ); + if ( this.logging.enabled ) console.info( 'Global output object count: ' + this.globalObjectCount ); }; return Parser; @@ -394,16 +442,16 @@ var maxQueueSize = 1024; var maxWebWorkers = 4; var radius = 640; - var logger = new THREE.LoaderSupport.ConsoleLogger( false ); - var workerDirector = new THREE.LoaderSupport.WorkerDirector( MeshSpray, logger ); + var workerDirector = new THREE.LoaderSupport.WorkerDirector( MeshSpray ); + workerDirector.setLogging( false, false ); workerDirector.setCrossOrigin( 'anonymous' ); var callbackOnLoad = function ( event ) { - logger.logInfo( 'Worker #' + event.detail.instanceNo + ': Completed loading. (#' + workerDirector.objectsCompleted + ')' ); + console.info( 'Worker #' + event.detail.instanceNo + ': Completed loading. (#' + workerDirector.objectsCompleted + ')' ); }; var reportProgress = function( event ) { document.getElementById( 'feedback' ).innerHTML = event.detail.text; - logger.logInfo( event.detail.text ); + console.info( event.detail.text ); }; var callbackMeshAlter = function ( event ) { var override = new THREE.LoaderSupport.LoadedMeshUserOverride( false, true ); @@ -439,7 +487,8 @@ z = r * Math.cos( t ); pivot.position.set( x, y, z ); this.scene.add( pivot ); - prepData.setStreamMeshesTo( pivot ); + prepData.streamMeshesTo = pivot; + prepData.setLogging( false, false ); prepData.quantity = 8192; prepData.dimension = Math.max( Math.random() * 500, 100 ); diff --git a/examples/webgl_loader_obj2_options.html b/examples/webgl_loader_obj2_options.html index ddc8fafcf5..72dee42810 100644 --- a/examples/webgl_loader_obj2_options.html +++ b/examples/webgl_loader_obj2_options.html @@ -277,7 +277,7 @@ local.position.set( 0, 0, 100 ); local.scale.set( 50.0, 50.0, 50.0 ); this.pivot.add( local ); - prepData.setStreamMeshesTo( local ); + prepData.streamMeshesTo = local; prepData.addResource( new THREE.LoaderSupport.ResourceDescriptor( 'models/obj/cerberus/Cerberus.obj', 'OBJ' ) ); var callbacks = prepData.getCallbacks(); callbacks.setCallbackOnProgress( this._reportProgress ); @@ -298,9 +298,9 @@ local.position.set( 125, 50, 0 ); local.name = 'Pivot_vive-controller'; this.pivot.add( local ); - prepData.setStreamMeshesTo( local ); + prepData.streamMeshesTo = local; prepData.addResource( new THREE.LoaderSupport.ResourceDescriptor( 'models/obj/vive-controller/vr_controller_vive_1_5.obj', 'OBJ' ) ); - prepData.setUseAsync( true ); + prepData.useAsync = true; var callbacks = prepData.getCallbacks(); var callbackMeshAlter = function ( event ) { var override = new THREE.LoaderSupport.LoadedMeshUserOverride( false, true ); diff --git a/examples/webgl_loader_obj2_run_director.html b/examples/webgl_loader_obj2_run_director.html index 8f68c99dad..0a5c3bbf08 100644 --- a/examples/webgl_loader_obj2_run_director.html +++ b/examples/webgl_loader_obj2_run_director.html @@ -111,10 +111,14 @@ this.camera = null; this.cameraTarget = this.cameraDefaults.posCameraTarget; - this.logger = new THREE.LoaderSupport.ConsoleLogger(); - this.logger.setEnabled( false ); - this.workerDirector = new THREE.LoaderSupport.WorkerDirector( THREE.OBJLoader2, this.logger ); + this.workerDirector = new THREE.LoaderSupport.WorkerDirector( THREE.OBJLoader2 ); + this.logging = { + enabled: false, + debug: false + }; + this.workerDirector.setLogging( this.logging.enabled, this.logging.debug ); this.workerDirector.setCrossOrigin( 'anonymous' ); + this.workerDirector.setForceWorkerDataCopy( true ); this.controls = null; this.cube = null; @@ -199,7 +203,7 @@ if ( Validator.isValid( content ) && Validator.isValid( content.detail ) ) output = content.detail.text; output = Validator.verifyInput( output, '' ); - this.logger.logInfo( 'Progress:\n\t' + output.replace(/\/g, '\n\t' ) ); + if ( this.logging.enabled ) console.info( 'Progress:\n\t' + output.replace(/\/g, '\n\t' ) ); document.getElementById( 'feedback' ).innerHTML = output; }; @@ -234,7 +238,7 @@ scope.allAssets.push( event.detail.loaderRootNode ); var msg = 'Worker #' + instanceNo + ': Completed loading: ' + event.detail.modelName + ' (#' + scope.workerDirector.objectsCompleted + ')'; - scope.logger.logInfo( msg ); + if ( scope.logging.enabled ) console.info( msg ); scope.feedbackArray[ instanceNo ] = msg; scope._reportProgress( scope.feedbackArray.join( '\' ) ); @@ -247,7 +251,7 @@ if ( scope.reportDonwload[ instanceNo ] ) { var msg = 'Worker #' + instanceNo + ': ' + text; - scope.logger.logInfo( msg ); + if ( scope.logging.enabled ) console.info( msg ); scope.feedbackArray[ instanceNo ] = msg; scope._reportProgress( scope.feedbackArray.join( '\' ) ); @@ -279,32 +283,37 @@ callbacks.setCallbackOnMeshAlter( callbackMeshAlter ); this.workerDirector.prepareWorkers( callbacks, maxQueueSize, maxWebWorkers ); - this.logger.logInfo( 'Configuring WWManager with queue size ' + this.workerDirector.getMaxQueueSize() + ' and ' + this.workerDirector.getMaxWebWorkers() + ' workers.' ); + if ( this.logging.enabled ) console.info( 'Configuring WWManager with queue size ' + this.workerDirector.getMaxQueueSize() + ' and ' + this.workerDirector.getMaxWebWorkers() + ' workers.' ); var modelPrepDatas = []; prepData = new THREE.LoaderSupport.PrepData( 'male02' ); prepData.addResource( new THREE.LoaderSupport.ResourceDescriptor( 'models/obj/male02/male02.obj', 'OBJ ') ); prepData.addResource( new THREE.LoaderSupport.ResourceDescriptor( 'models/obj/male02/male02.mtl', 'MTL' ) ); + prepData.setLogging( false, false ); modelPrepDatas.push( prepData ); prepData = new THREE.LoaderSupport.PrepData( 'female02' ); prepData.addResource( new THREE.LoaderSupport.ResourceDescriptor( 'models/obj/female02/female02.obj', 'OBJ' ) ); prepData.addResource( new THREE.LoaderSupport.ResourceDescriptor( 'models/obj/female02/female02.mtl', 'MTL' ) ); + prepData.setLogging( false, false ); modelPrepDatas.push( prepData ); prepData = new THREE.LoaderSupport.PrepData( 'viveController' ); prepData.addResource( new THREE.LoaderSupport.ResourceDescriptor( 'models/obj/vive-controller/vr_controller_vive_1_5.obj', 'OBJ' ) ); + prepData.setLogging( false, false ); prepData.scale = 400.0; modelPrepDatas.push( prepData ); prepData = new THREE.LoaderSupport.PrepData( 'cerberus' ); prepData.addResource( new THREE.LoaderSupport.ResourceDescriptor( 'models/obj/cerberus/Cerberus.obj', 'OBJ' ) ); + prepData.setLogging( false, false ); prepData.scale = 50.0; modelPrepDatas.push( prepData ); prepData = new THREE.LoaderSupport.PrepData( 'WaltHead' ); prepData.addResource( new THREE.LoaderSupport.ResourceDescriptor( 'models/obj/walt/WaltHead.obj', 'OBJ' ) ); prepData.addResource( new THREE.LoaderSupport.ResourceDescriptor( 'models/obj/walt/WaltHead.mtl', 'MTL' ) ); + prepData.setLogging( false, false ); modelPrepDatas.push( prepData ); var pivot; @@ -319,6 +328,7 @@ modelPrepDataIndex = Math.floor( Math.random() * modelPrepDatas.length ); modelPrepData = modelPrepDatas[ modelPrepDataIndex ]; + modelPrepData.useAsync = true; scale = Validator.verifyInput( modelPrepData.scale, 0 ); modelPrepData = modelPrepData.clone(); @@ -330,12 +340,10 @@ ); if ( scale > 0 ) pivot.scale.set( scale, scale, scale ); this.scene.add( pivot ); - modelPrepData.setStreamMeshesTo( pivot ); - modelPrepData.setUseAsync( true ); + modelPrepData.streamMeshesTo = pivot; this.workerDirector.enqueueForRun( modelPrepData ); } - this.workerDirector.processQueue(); }; @@ -349,7 +357,7 @@ if ( storedObject3d === object3d ) return; - scope.logger.logInfo( 'Removing ' + object3d.name ); + if ( scope.logging.enabled ) console.info( 'Removing ' + object3d.name ); scope.scene.remove( object3d ); if ( object3d.hasOwnProperty( 'geometry' ) ) object3d.geometry.dispose(); -- GitLab