UNPKG

itowns

Version:

A JS/WebGL framework for 3D geospatial data visualization

168 lines (159 loc) 7.45 kB
import * as THREE from 'three'; import LegacyGLTFLoader from "./deprecated/LegacyGLTFLoader.js"; import { GLTFLoader } from "../ThreeExtended/loaders/GLTFLoader.js"; class iGLTFLoader extends THREE.Loader { /** * Parses [glTF](https://www.khronos.org/gltf/) 1.0 and 2.0 files. * * Under the hood, glTF 2.0 files are parsed with THREE.GLTFLoader and GLTF 1.0 are parsed with the previous THREE * GltfLoader (for 1.0 glTF) that has been kept and maintained in iTowns. * * Beware that gltf convention is y-up while itowns is z-up. You can apply a PI/2 rotation around the X axis to the * loaded model to transform from y-up to z-up. Note that you can also use Coordinates.geodesicNormal to get the normal * to a position on the globe (i.e. in GlobeView) to correctly orient a model on a GlobeView. * * @param {THREE.LoadingManager} [manager] - The loadingManager for the loader to use. Default is THREE.DefaultLoadingManager. */ constructor(manager) { super(manager); this.legacyGLTFLoader = new LegacyGLTFLoader(); this.glTFLoader = new GLTFLoader(); } /** * Loads a gltf model from url and call the callback function with the parsed response content. * Adapted from threejs. * @param {String} url - the path/URL of the .gltf or .glb file. * @param {Function} onLoad - A function to be called after the loading is successfully completed. The function * receives the loaded JSON response returned from {@link parse}. * @param {Function} onProgress * @param {Function} onError */ load(url, onLoad, onProgress, onError) { const scope = this; let resourcePath; if (this.resourcePath !== '') { resourcePath = this.resourcePath; } else if (this.path !== '') { // If a base path is set, resources will be relative paths from that plus the relative path of the gltf file // Example path = 'https://my-cnd-server.com/', url = 'assets/models/model.gltf' // resourcePath = 'https://my-cnd-server.com/assets/models/' // referenced resource 'model.bin' will be loaded from 'https://my-cnd-server.com/assets/models/model.bin' // referenced resource '../textures/texture.png' will be loaded from 'https://my-cnd-server.com/assets/textures/texture.png' const relativeUrl = THREE.LoaderUtils.extractUrlBase(url); resourcePath = THREE.LoaderUtils.resolveURL(relativeUrl, this.path); } else { resourcePath = THREE.LoaderUtils.extractUrlBase(url); } // Tells the LoadingManager to track an extra item, which resolves after // the model is fully loaded. This means the count of items loaded will // be incorrect, but ensures manager.onLoad() does not fire early. this.manager.itemStart(url); const _onError = e => { if (onError) { onError(e); } else { console.error(e); } scope.manager.itemError(url); scope.manager.itemEnd(url); }; const loader = new THREE.FileLoader(this.manager); loader.setPath(this.path); loader.setResponseType('arraybuffer'); loader.setRequestHeader(this.requestHeader); loader.setWithCredentials(this.withCredentials); loader.load(url, data => { try { scope.parse(data, resourcePath, gltf => { onLoad(gltf); scope.manager.itemEnd(url); }, _onError); } catch (e) { _onError(e); } }, onProgress, _onError); } /** * Sets the draco loader instance for this gltf parser. Enable loading files with * [Draco](https://google.github.io/draco/) geometry extension. See Threejs * [DracoLoader](https://threejs.org/docs/index.html#examples/en/loaders/DRACOLoader) for more information. * Only works for GLTF 2.0 files. * @param {THREE.DracoLoader} dracoLoader - the threejs DracoLoader instance. */ setDRACOLoader(dracoLoader) { this.glTFLoader.setDRACOLoader(dracoLoader); } /** * Sets the KTX2 loader instance for this gltf parser. Enable loading files with * [KTX2](https://www.khronos.org/ktx/) texture extension. See Threejs * [KTX2Loader](https://threejs.org/docs/index.html?q=KTX2#examples/en/loaders/KTX2Loader) for more information. * Only works for GLTF 2.0 files. * @param {THREE.KTX2Loader} ktx2Loader - the threejs KTX2Loader instance. */ setKTX2Loader(ktx2Loader) { this.glTFLoader.setKTX2Loader(ktx2Loader); } /** * Sets the Mesh Optimizer decoder instance for this gltf parser. Enable loading files with * [MeshOptimizer](https://meshoptimizer.org/) geometry extension. * Only works for GLTF 2.0 files. * @param {Object} meshoptDecoder - the threejs meshopt decoder instance. */ setMeshoptDecoder(meshoptDecoder) { this.glTFLoader.setMeshoptDecoder(meshoptDecoder); } /** * Registers a callback to load specific unknown or not standard GLTF extensions. * See Threejs [GltfLoader](https://threejs.org/docs/?q=gltflo#examples/en/loaders/GLTFLoader) for more * information. * @param {Function} callback - the callback function */ register(callback) { this.glTFLoader.register(callback); } /** * Unregisters a load callback. * See Threejs [GltfLoader](https://threejs.org/docs/?q=gltflo#examples/en/loaders/GLTFLoader) for more * information. * @param {Function} callback - the callback function */ unregister(callback) { this.glTFLoader.unregister(callback); } /** Parse a glTF-based ArrayBuffer, JSON string or object and fire onLoad callback when complete. * Calls Threejs [GLTFLoader.parse](https://threejs.org/docs/?q=gltflo#examples/en/loaders/GLTFLoader.parse) for * glTF 2.0 files and LegacyGLTFLoader.parse for gtTF 1.0 files. * @param {ArrayBuffer|String|Object} buffer - the glTF asset to parse, as an ArrayBuffer, JSON string or object. * @param {String} path - the base path from which to find subsequent glTF resources such as textures and .bin data files. * @param {Function} onLoad — A function to be called when parse completes. The argument to the onLoad function will * be an Object that contains loaded parts: .scene, .scenes, .cameras, .animations, and .asset. * @param {Function} [onError] — A function to be called if an error occurs during parsing. The function receives error as an argument. */ parse(buffer, path, onLoad, onError) { if (!buffer || !path) { onError('[iGLTFLoader]: Buffer and path are mandatory to parse a glTF.'); return; } const headerView = new DataView(buffer, 0, 20); const version = headerView.getUint32(4, true); if (version === 1) { this.legacyGLTFLoader.parse(buffer, path, onLoad, onError); } else { this.glTFLoader.parse(buffer, path, onLoad, onError); } } /** * Async promise-based parsing of a glTF-based ArrayBuffer, JSON string or object. * @param {ArrayBuffer|String|Object} data - the glTF asset to parse, as an ArrayBuffer, JSON string or object. * @param {String} path - the base path from which to find subsequent glTF resources such as textures and .bin data files. * @returns {Promise<Object>} A promise that resolves an Object that contains loaded parts: * .scene, .scenes, .cameras, .animations, and .asset, when parsing is done. */ parseAsync(data, path) { const scope = this; return new Promise((resolve, reject) => { scope.parse(data, path, resolve, reject); }); } } export default iGLTFLoader;