|
@@ -4,9 +4,10 @@
|
|
*/
|
|
*/
|
|
|
|
|
|
import {
|
|
import {
|
|
- DefaultLoadingManager,
|
|
|
|
|
|
+ LoadingManager,
|
|
FileLoader,
|
|
FileLoader,
|
|
- Group
|
|
|
|
|
|
+ Object3D,
|
|
|
|
+ Loader
|
|
} from "../../../build/three.module.js";
|
|
} from "../../../build/three.module.js";
|
|
|
|
|
|
import { OBJLoader2Parser } from "./obj2/worker/parallel/OBJLoader2Parser.js";
|
|
import { OBJLoader2Parser } from "./obj2/worker/parallel/OBJLoader2Parser.js";
|
|
@@ -14,272 +15,362 @@ import { MeshReceiver } from "./obj2/shared/MeshReceiver.js";
|
|
import { MaterialHandler } from "./obj2/shared/MaterialHandler.js";
|
|
import { MaterialHandler } from "./obj2/shared/MaterialHandler.js";
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Use this class to load OBJ data from files or to parse OBJ data from an arraybuffer
|
|
|
|
- * @class
|
|
|
|
|
|
+ * Creates a new OBJLoader2. Use it to load OBJ data from files or to parse OBJ data from arraybuffer or text.
|
|
*
|
|
*
|
|
- * @param {DefaultLoadingManager} [manager] The loadingManager for the loader to use. Default is {@link DefaultLoadingManager}
|
|
|
|
|
|
+ * @param {LoadingManager} [manager] The loadingManager for the loader to use. Default is {@link LoadingManager}
|
|
|
|
+ * @constructor
|
|
*/
|
|
*/
|
|
const OBJLoader2 = function ( manager ) {
|
|
const OBJLoader2 = function ( manager ) {
|
|
|
|
+ Loader.call( this, manager );
|
|
|
|
|
|
- OBJLoader2Parser.call( this );
|
|
|
|
- this.manager = ( manager !== undefined && manager !== null ) ? manager : DefaultLoadingManager;
|
|
|
|
|
|
+ this.parser = new OBJLoader2Parser();
|
|
|
|
|
|
this.modelName = '';
|
|
this.modelName = '';
|
|
this.instanceNo = 0;
|
|
this.instanceNo = 0;
|
|
- this.path = undefined;
|
|
|
|
- this.resourcePath = undefined;
|
|
|
|
- this.baseObject3d = new Group();
|
|
|
|
|
|
+ this.baseObject3d = new Object3D();
|
|
|
|
|
|
this.materialHandler = new MaterialHandler();
|
|
this.materialHandler = new MaterialHandler();
|
|
this.meshReceiver = new MeshReceiver( this.materialHandler );
|
|
this.meshReceiver = new MeshReceiver( this.materialHandler );
|
|
|
|
|
|
|
|
+ // as OBJLoader2 is no longer derived from OBJLoader2Parser, we need to override the default onAssetAvailable callback
|
|
|
|
+ let scope = this;
|
|
|
|
+ let defaultOnAssetAvailable = function ( payload ) {
|
|
|
|
+ scope._onAssetAvailable( payload )
|
|
|
|
+ };
|
|
|
|
+ this.parser.setCallbackOnAssetAvailable( defaultOnAssetAvailable );
|
|
};
|
|
};
|
|
-OBJLoader2.OBJLOADER2_VERSION = '3.0.0';
|
|
|
|
|
|
+
|
|
|
|
+OBJLoader2.OBJLOADER2_VERSION = '3.1.0';
|
|
console.info( 'Using OBJLoader2 version: ' + OBJLoader2.OBJLOADER2_VERSION );
|
|
console.info( 'Using OBJLoader2 version: ' + OBJLoader2.OBJLOADER2_VERSION );
|
|
|
|
|
|
-OBJLoader2.prototype = Object.create( OBJLoader2Parser.prototype );
|
|
|
|
-OBJLoader2.prototype.constructor = OBJLoader2;
|
|
|
|
|
|
|
|
|
|
+OBJLoader2.prototype = Object.assign( Object.create( Loader.prototype ), {
|
|
|
|
|
|
-/**
|
|
|
|
- * Set the name of the model.
|
|
|
|
- *
|
|
|
|
- * @param {string} modelName
|
|
|
|
- * @return {OBJLoader2}
|
|
|
|
- */
|
|
|
|
-OBJLoader2.prototype.setModelName = function ( modelName ) {
|
|
|
|
|
|
+ constructor: OBJLoader2,
|
|
|
|
|
|
- this.modelName = modelName ? modelName : this.modelName;
|
|
|
|
- return this;
|
|
|
|
|
|
+ /**
|
|
|
|
+ * See {@link OBJLoader2Parser.setLogging}
|
|
|
|
+ * @return {OBJLoader2}
|
|
|
|
+ */
|
|
|
|
+ setLogging: function ( enabled, debug ) {
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ this.parser.setLogging( enabled, debug );
|
|
|
|
+ return this;
|
|
|
|
|
|
-/**
|
|
|
|
- * The URL of the base path.
|
|
|
|
- *
|
|
|
|
- * @param {string} path URL
|
|
|
|
- * @return {OBJLoader2}
|
|
|
|
- */
|
|
|
|
-OBJLoader2.prototype.setPath = function ( path ) {
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- this.path = path ? path : this.path;
|
|
|
|
- return this;
|
|
|
|
|
|
+ /**
|
|
|
|
+ * See {@link OBJLoader2Parser.setMaterialPerSmoothingGroup}
|
|
|
|
+ * @return {OBJLoader2}
|
|
|
|
+ */
|
|
|
|
+ setMaterialPerSmoothingGroup: function ( materialPerSmoothingGroup ) {
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ this.parser.setMaterialPerSmoothingGroup( materialPerSmoothingGroup );
|
|
|
|
+ return this;
|
|
|
|
|
|
-/**
|
|
|
|
- * Allow to specify resourcePath for dependencies of specified resource.
|
|
|
|
- *
|
|
|
|
- * @param {string} resourcePath
|
|
|
|
- * @return {OBJLoader2}
|
|
|
|
- */
|
|
|
|
-OBJLoader2.prototype.setResourcePath = function ( resourcePath ) {
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- this.resourcePath = resourcePath ? resourcePath : this.resourcePath;
|
|
|
|
- return this;
|
|
|
|
|
|
+ /**
|
|
|
|
+ * See {@link OBJLoader2Parser.setUseOAsMesh}
|
|
|
|
+ * @return {OBJLoader2}
|
|
|
|
+ */
|
|
|
|
+ setUseOAsMesh: function ( useOAsMesh ) {
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ this.parser.setUseOAsMesh( useOAsMesh );
|
|
|
|
+ return this;
|
|
|
|
|
|
-/**
|
|
|
|
- * Set the node where the loaded objects will be attached directly.
|
|
|
|
- *
|
|
|
|
- * @param {Object3D} baseObject3d Object already attached to scenegraph where new meshes will be attached to
|
|
|
|
- * @return {OBJLoader2}
|
|
|
|
- */
|
|
|
|
-OBJLoader2.prototype.setBaseObject3d = function ( baseObject3d ) {
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- this.baseObject3d = ( baseObject3d === undefined || baseObject3d === null ) ? this.baseObject3d : baseObject3d;
|
|
|
|
- return this;
|
|
|
|
|
|
+ /**
|
|
|
|
+ * See {@link OBJLoader2Parser.setUseIndices}
|
|
|
|
+ * @return {OBJLoader2}
|
|
|
|
+ */
|
|
|
|
+ setUseIndices: function ( useIndices ) {
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ this.parser.setUseIndices( useIndices );
|
|
|
|
+ return this;
|
|
|
|
|
|
-/**
|
|
|
|
- * Add materials as associated array.
|
|
|
|
- *
|
|
|
|
- * @param {Object} materials Object with named {@link Material}
|
|
|
|
- * @return {OBJLoader2}
|
|
|
|
- */
|
|
|
|
-OBJLoader2.prototype.addMaterials = function ( materials ) {
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- this.materialHandler.addMaterials( materials );
|
|
|
|
- return this;
|
|
|
|
|
|
+ /**
|
|
|
|
+ * See {@link OBJLoader2Parser.setDisregardNormals}
|
|
|
|
+ * @return {OBJLoader2}
|
|
|
|
+ */
|
|
|
|
+ setDisregardNormals: function ( disregardNormals ) {
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ this.parser.setDisregardNormals( disregardNormals );
|
|
|
|
+ return this;
|
|
|
|
|
|
-/**
|
|
|
|
- * Register a function that is called once a single mesh is available and it could be altered by the supplied function.
|
|
|
|
- *
|
|
|
|
- * @param {Function} [onMeshAlter]
|
|
|
|
- * @return {OBJLoader2}
|
|
|
|
- */
|
|
|
|
-OBJLoader2.prototype.setCallbackOnMeshAlter = function ( onMeshAlter ) {
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- this.meshReceiver._setCallbacks( this.callbacks.onProgress, onMeshAlter );
|
|
|
|
- return this;
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Set the name of the model.
|
|
|
|
+ *
|
|
|
|
+ * @param {string} modelName
|
|
|
|
+ * @return {OBJLoader2}
|
|
|
|
+ */
|
|
|
|
+ setModelName: function ( modelName ) {
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ this.modelName = modelName ? modelName : this.modelName;
|
|
|
|
+ return this;
|
|
|
|
|
|
-/**
|
|
|
|
- * Register a function that is called once all materials have been loaded and they could be altered by the supplied function.
|
|
|
|
- *
|
|
|
|
- * @param {Function} [onLoadMaterials]
|
|
|
|
- * @return {OBJLoader2}
|
|
|
|
- */
|
|
|
|
-OBJLoader2.prototype.setCallbackOnLoadMaterials = function ( onLoadMaterials ) {
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- this.materialHandler._setCallbacks( onLoadMaterials );
|
|
|
|
- return this;
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Set the node where the loaded objects will be attached directly.
|
|
|
|
+ *
|
|
|
|
+ * @param {Object3D} baseObject3d Object already attached to scenegraph where new meshes will be attached to
|
|
|
|
+ * @return {OBJLoader2}
|
|
|
|
+ */
|
|
|
|
+ setBaseObject3d: function ( baseObject3d ) {
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ this.baseObject3d = (baseObject3d === undefined || baseObject3d === null) ? this.baseObject3d : baseObject3d;
|
|
|
|
+ return this;
|
|
|
|
|
|
-/**
|
|
|
|
- * Use this convenient method to load a file at the given URL. By default the fileLoader uses an ArrayBuffer.
|
|
|
|
- *
|
|
|
|
- * @param {string} url A string containing the path/URL of the file to be loaded.
|
|
|
|
- * @param {function} onLoad A function to be called after loading is successfully completed. The function receives loaded Object3D as an argument.
|
|
|
|
- * @param {function} [onFileLoadProgress] 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 {function} [onError] A function to be called if an error occurs during loading. The function receives the error as an argument.
|
|
|
|
- * @param {function} [onMeshAlter] Called after every single mesh is made available by the parser
|
|
|
|
- */
|
|
|
|
-OBJLoader2.prototype.load = function ( url, onLoad, onFileLoadProgress, onError, onMeshAlter ) {
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- let scope = this;
|
|
|
|
- if ( onLoad === null || onLoad === undefined || ! ( onLoad instanceof Function ) ) {
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Add materials as associated array.
|
|
|
|
+ *
|
|
|
|
+ * @param {Object} materials Object with named {@link Material}
|
|
|
|
+ * @return {OBJLoader2}
|
|
|
|
+ */
|
|
|
|
+ addMaterials: function ( materials ) {
|
|
|
|
|
|
- let errorMessage = 'onLoad is not a function! Aborting...';
|
|
|
|
- scope.callbacks.onError( errorMessage );
|
|
|
|
- throw errorMessage
|
|
|
|
|
|
+ this.materialHandler.addMaterials( materials );
|
|
|
|
+ return this;
|
|
|
|
|
|
- }
|
|
|
|
- if ( onError === null || onError === undefined || ! ( onError instanceof Function ) ) {
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- onError = function ( event ) {
|
|
|
|
|
|
+ /**
|
|
|
|
+ * See {@link OBJLoader2Parser.setCallbackOnAssetAvailable}
|
|
|
|
+ * @return {OBJLoader2}
|
|
|
|
+ */
|
|
|
|
+ setCallbackOnAssetAvailable: function ( onAssetAvailable ) {
|
|
|
|
|
|
- let errorMessage = event;
|
|
|
|
- if ( event.currentTarget && event.currentTarget.statusText !== null ) {
|
|
|
|
|
|
+ this.parser.setCallbackOnAssetAvailable( onAssetAvailable );
|
|
|
|
+ return this;
|
|
|
|
|
|
- errorMessage = 'Error occurred while downloading!\nurl: ' + event.currentTarget.responseURL + '\nstatus: ' + event.currentTarget.statusText;
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- }
|
|
|
|
- scope.callbacks.onError( errorMessage );
|
|
|
|
|
|
+ /**
|
|
|
|
+ * See {@link OBJLoader2Parser.setCallbackOnProgress}
|
|
|
|
+ * @return {OBJLoader2}
|
|
|
|
+ */
|
|
|
|
+ setCallbackOnProgress: function ( onProgress ) {
|
|
|
|
|
|
- };
|
|
|
|
|
|
+ this.parser.setCallbackOnProgress( onProgress );
|
|
|
|
+ return this;
|
|
|
|
|
|
- }
|
|
|
|
- if ( ! url ) {
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- onError( 'An invalid url was provided. Unable to continue!' );
|
|
|
|
|
|
+ /**
|
|
|
|
+ * See {@link OBJLoader2Parser.setCallbackOnError}
|
|
|
|
+ * @return {OBJLoader2}
|
|
|
|
+ */
|
|
|
|
+ setCallbackOnError: function ( onError ) {
|
|
|
|
|
|
- }
|
|
|
|
- let urlFull = new URL( url, window.location.href ).href;
|
|
|
|
- let filename = urlFull;
|
|
|
|
- let urlParts = urlFull.split( '/' );
|
|
|
|
- if ( urlParts.length > 2 ) {
|
|
|
|
|
|
+ this.parser.setCallbackOnError( onError );
|
|
|
|
+ return this;
|
|
|
|
|
|
- filename = urlParts[ urlParts.length - 1 ];
|
|
|
|
- let urlPartsPath = urlParts.slice( 0, urlParts.length - 1 ).join( '/' ) + '/';
|
|
|
|
- if ( urlPartsPath !== undefined && urlPartsPath !== null ) this.path = urlPartsPath;
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- }
|
|
|
|
- if ( onFileLoadProgress === null || onFileLoadProgress === undefined || ! ( onFileLoadProgress instanceof Function ) ) {
|
|
|
|
|
|
+ /**
|
|
|
|
+ * See {@link OBJLoader2Parser.setCallbackOnLoad}
|
|
|
|
+ * @return {OBJLoader2}
|
|
|
|
+ */
|
|
|
|
+ setCallbackOnLoad: function ( onLoad ) {
|
|
|
|
|
|
- let numericalValueRef = 0;
|
|
|
|
- let numericalValue = 0;
|
|
|
|
- onFileLoadProgress = function ( event ) {
|
|
|
|
|
|
+ this.parser.setCallbackOnLoad( onLoad );
|
|
|
|
+ return this;
|
|
|
|
|
|
- if ( ! event.lengthComputable ) return;
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- numericalValue = event.loaded / event.total;
|
|
|
|
- if ( numericalValue > numericalValueRef ) {
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Register a function that is called once a single mesh is available and it could be altered by the supplied function.
|
|
|
|
+ *
|
|
|
|
+ * @param {Function} [onMeshAlter]
|
|
|
|
+ * @return {OBJLoader2}
|
|
|
|
+ */
|
|
|
|
+ setCallbackOnMeshAlter: function ( onMeshAlter ) {
|
|
|
|
+
|
|
|
|
+ this.meshReceiver._setCallbacks( this.parser.callbacks.onProgress, onMeshAlter );
|
|
|
|
+ return this;
|
|
|
|
|
|
- numericalValueRef = numericalValue;
|
|
|
|
- let output = 'Download of "' + url + '": ' + ( numericalValue * 100 ).toFixed( 2 ) + '%';
|
|
|
|
- scope.callbacks.onProgress( 'progressLoad', output, numericalValue );
|
|
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Register a function that is called once all materials have been loaded and they could be altered by the supplied function.
|
|
|
|
+ *
|
|
|
|
+ * @param {Function} [onLoadMaterials]
|
|
|
|
+ * @return {OBJLoader2}
|
|
|
|
+ */
|
|
|
|
+ setCallbackOnLoadMaterials: function ( onLoadMaterials ) {
|
|
|
|
+
|
|
|
|
+ this.materialHandler._setCallbacks( onLoadMaterials );
|
|
|
|
+ return this;
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- };
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Use this convenient method to load a file at the given URL. By default the fileLoader uses an ArrayBuffer.
|
|
|
|
+ *
|
|
|
|
+ * @param {string} url A string containing the path/URL of the file to be loaded.
|
|
|
|
+ * @param {function} onLoad A function to be called after loading is successfully completed. The function receives loaded Object3D as an argument.
|
|
|
|
+ * @param {function} [onFileLoadProgress] 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 {function} [onError] A function to be called if an error occurs during loading. The function receives the error as an argument.
|
|
|
|
+ * @param {function} [onMeshAlter] Called after every single mesh is made available by the parser
|
|
|
|
+ */
|
|
|
|
+ load: function ( url, onLoad, onFileLoadProgress, onError, onMeshAlter ) {
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ let scope = this;
|
|
|
|
+ if ( onLoad === null || onLoad === undefined || !(onLoad instanceof Function) ) {
|
|
|
|
+
|
|
|
|
+ let errorMessage = 'onLoad is not a function! Aborting...';
|
|
|
|
+ scope.parser.callbacks.onError( errorMessage );
|
|
|
|
+ throw errorMessage
|
|
|
|
|
|
- this.setCallbackOnMeshAlter( onMeshAlter );
|
|
|
|
- let fileLoaderOnLoad = function ( content ) {
|
|
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
|
|
- onLoad( scope.parse( content ) );
|
|
|
|
|
|
+ this.parser.setCallbackOnLoad( onLoad );
|
|
|
|
|
|
- };
|
|
|
|
- let fileLoader = new FileLoader( this.manager );
|
|
|
|
- fileLoader.setPath( this.path || this.resourcePath );
|
|
|
|
- fileLoader.setResponseType( 'arraybuffer' );
|
|
|
|
- fileLoader.load( filename, fileLoaderOnLoad, onFileLoadProgress, onError );
|
|
|
|
|
|
+ }
|
|
|
|
+ if ( onError === null || onError === undefined || !(onError instanceof Function) ) {
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ onError = function ( event ) {
|
|
|
|
|
|
-/**
|
|
|
|
- * Parses OBJ data synchronously from arraybuffer or string.
|
|
|
|
- *
|
|
|
|
- * @param {arraybuffer|string} content OBJ data as Uint8Array or String
|
|
|
|
- */
|
|
|
|
-OBJLoader2.prototype.parse = function ( content ) {
|
|
|
|
|
|
+ let errorMessage = event;
|
|
|
|
+ if ( event.currentTarget && event.currentTarget.statusText !== null ) {
|
|
|
|
|
|
- // fast-fail in case of illegal data
|
|
|
|
- if ( content === null || content === undefined ) {
|
|
|
|
|
|
+ errorMessage = 'Error occurred while downloading!\nurl: ' + event.currentTarget.responseURL + '\nstatus: ' + event.currentTarget.statusText;
|
|
|
|
|
|
- throw 'Provided content is not a valid ArrayBuffer or String. Unable to continue parsing';
|
|
|
|
|
|
+ }
|
|
|
|
+ scope.parser.callbacks.onError( errorMessage );
|
|
|
|
|
|
- }
|
|
|
|
- if ( this.logging.enabled ) {
|
|
|
|
|
|
+ };
|
|
|
|
|
|
- console.time( 'OBJLoader parse: ' + this.modelName );
|
|
|
|
|
|
+ }
|
|
|
|
+ if ( !url ) {
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ onError( 'An invalid url was provided. Unable to continue!' );
|
|
|
|
|
|
- // sync code works directly on the material references
|
|
|
|
- this._setMaterials( this.materialHandler.getMaterials() );
|
|
|
|
|
|
+ }
|
|
|
|
+ let urlFull = new URL( url, window.location.href ).href;
|
|
|
|
+ let filename = urlFull;
|
|
|
|
+ let urlParts = urlFull.split( '/' );
|
|
|
|
+ if ( urlParts.length > 2 ) {
|
|
|
|
|
|
- if ( content instanceof ArrayBuffer || content instanceof Uint8Array ) {
|
|
|
|
|
|
+ filename = urlParts[ urlParts.length - 1 ];
|
|
|
|
+ let urlPartsPath = urlParts.slice( 0, urlParts.length - 1 ).join( '/' ) + '/';
|
|
|
|
+ if ( urlPartsPath !== undefined && urlPartsPath !== null ) this.path = urlPartsPath;
|
|
|
|
|
|
- if ( this.logging.enabled ) console.info( 'Parsing arrayBuffer...' );
|
|
|
|
- this.execute( content );
|
|
|
|
|
|
+ }
|
|
|
|
+ if ( onFileLoadProgress === null || onFileLoadProgress === undefined || !(onFileLoadProgress instanceof Function) ) {
|
|
|
|
|
|
- } else if ( typeof ( content ) === 'string' || content instanceof String ) {
|
|
|
|
|
|
+ let numericalValueRef = 0;
|
|
|
|
+ let numericalValue = 0;
|
|
|
|
+ onFileLoadProgress = function ( event ) {
|
|
|
|
|
|
- if ( this.logging.enabled ) console.info( 'Parsing text...' );
|
|
|
|
- this.executeLegacy( content );
|
|
|
|
|
|
+ if ( !event.lengthComputable ) return;
|
|
|
|
|
|
- } else {
|
|
|
|
|
|
+ numericalValue = event.loaded / event.total;
|
|
|
|
+ if ( numericalValue > numericalValueRef ) {
|
|
|
|
|
|
- this.callbacks.onError( 'Provided content was neither of type String nor Uint8Array! Aborting...' );
|
|
|
|
|
|
+ numericalValueRef = numericalValue;
|
|
|
|
+ let output = 'Download of "' + url + '": ' + (numericalValue * 100).toFixed( 2 ) + '%';
|
|
|
|
+ scope.parser.callbacks.onProgress( 'progressLoad', output, numericalValue );
|
|
|
|
|
|
- }
|
|
|
|
- if ( this.logging.enabled ) {
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- console.timeEnd( 'OBJLoader parse: ' + this.modelName );
|
|
|
|
|
|
+ };
|
|
|
|
|
|
- }
|
|
|
|
- return this.baseObject3d;
|
|
|
|
|
|
+ }
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ this.setCallbackOnMeshAlter( onMeshAlter );
|
|
|
|
+ let fileLoaderOnLoad = function ( content ) {
|
|
|
|
+
|
|
|
|
+ scope.parser.callbacks.onLoad( scope.parse( content ), "OBJLoader2#load: Parsing completed" );
|
|
|
|
|
|
-OBJLoader2.prototype._onAssetAvailable = function ( payload ) {
|
|
|
|
|
|
+ };
|
|
|
|
+ let fileLoader = new FileLoader( this.manager );
|
|
|
|
+ fileLoader.setPath( this.path || this.resourcePath );
|
|
|
|
+ fileLoader.setResponseType( 'arraybuffer' );
|
|
|
|
+ fileLoader.load( filename, fileLoaderOnLoad, onFileLoadProgress, onError );
|
|
|
|
|
|
- if ( payload.cmd !== 'assetAvailable' ) return;
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- if ( payload.type === 'mesh' ) {
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Parses OBJ data synchronously from arraybuffer or string and returns the {@link Object3D}.
|
|
|
|
+ *
|
|
|
|
+ * @param {arraybuffer|string} content OBJ data as Uint8Array or String
|
|
|
|
+ * @return {Object3D}
|
|
|
|
+ */
|
|
|
|
+ parse: function ( content ) {
|
|
|
|
|
|
- let meshes = this.meshReceiver.buildMeshes( payload );
|
|
|
|
- for ( let mesh of meshes ) {
|
|
|
|
|
|
+ // fast-fail in case of illegal data
|
|
|
|
+ if ( content === null || content === undefined ) {
|
|
|
|
|
|
- this.baseObject3d.add( mesh );
|
|
|
|
|
|
+ throw 'Provided content is not a valid ArrayBuffer or String. Unable to continue parsing';
|
|
|
|
|
|
}
|
|
}
|
|
|
|
+ if ( this.parser.logging.enabled ) {
|
|
|
|
+
|
|
|
|
+ console.time( 'OBJLoader parse: ' + this.modelName );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Create default materials beforehand, but do not override previously set materials (e.g. during init)
|
|
|
|
+ this.materialHandler.createDefaultMaterials( false );
|
|
|
|
+
|
|
|
|
+ // code works directly on the material references, parser clear its materials before updating
|
|
|
|
+ this.parser.setMaterials( this.materialHandler.getMaterials() );
|
|
|
|
|
|
- } else if ( payload.type === 'material' ) {
|
|
|
|
|
|
+ if ( content instanceof ArrayBuffer || content instanceof Uint8Array ) {
|
|
|
|
|
|
- this.materialHandler.addPayloadMaterials( payload );
|
|
|
|
|
|
+ if ( this.parser.logging.enabled ) console.info( 'Parsing arrayBuffer...' );
|
|
|
|
+ this.parser.execute( content );
|
|
|
|
+
|
|
|
|
+ } else if ( typeof (content) === 'string' || content instanceof String ) {
|
|
|
|
+
|
|
|
|
+ if ( this.parser.logging.enabled ) console.info( 'Parsing text...' );
|
|
|
|
+ this.parser.executeLegacy( content );
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ this.parser.callbacks.onError( 'Provided content was neither of type String nor Uint8Array! Aborting...' );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ if ( this.parser.logging.enabled ) {
|
|
|
|
+
|
|
|
|
+ console.timeEnd( 'OBJLoader parse: ' + this.modelName );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ return this.baseObject3d;
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ _onAssetAvailable: function ( payload ) {
|
|
|
|
+
|
|
|
|
+ if ( payload.cmd !== 'assetAvailable' ) return;
|
|
|
|
+
|
|
|
|
+ if ( payload.type === 'mesh' ) {
|
|
|
|
+
|
|
|
|
+ let meshes = this.meshReceiver.buildMeshes( payload );
|
|
|
|
+ for ( let mesh of meshes ) {
|
|
|
|
+
|
|
|
|
+ this.baseObject3d.add( mesh );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ } else if ( payload.type === 'material' ) {
|
|
|
|
+
|
|
|
|
+ this.materialHandler.addPayloadMaterials( payload );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-};
|
|
|
|
|
|
+} );
|
|
|
|
|
|
export { OBJLoader2 };
|
|
export { OBJLoader2 };
|