UNPKG

threepipe

Version:

A 3D viewer framework built on top of three.js in TypeScript with a focus on quality rendering, modularity and extensibility.

142 lines 7.27 kB
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'; import { OrthographicCamera } from 'three'; import { safeSetProperty } from 'ts-browser-helpers'; import { generateUUID } from '../../three'; import { glbEncryptionPreparser, GLTFLightExtrasExtension, GLTFMaterialExtrasExtension, GLTFMaterialsAlphaMapExtension, GLTFMaterialsBumpMapExtension, GLTFMaterialsDisplacementMapExtension, GLTFMaterialsLightMapExtension, GLTFObject3DExtrasExtension, GLTFViewerConfigExtension, } from '../gltf'; import { ThreeSerialization } from '../../utils'; import { DirectionalLight2, PerspectiveCamera0, PhysicalMaterial, PointLight2, SpotLight2, UnlitLineMaterial, UnlitMaterial, } from '../../core'; export class GLTFLoader2 extends GLTFLoader { constructor(manager) { super(manager); this.isGLTFLoader2 = true; /** * Preparsers are run on the arraybuffer/string before parsing to read the glb/gltf data */ this.preparsers = []; // loads the viewer config and handles loading the draco loader for extension this.gltfViewerParser = (viewer) => { return (parser) => { const getDependency = parser.getDependency; parser.getDependency = async (type, index) => { const res = await getDependency.call(parser, type, index); if (res && res.userData) { const gltfExtensions = res.userData.gltfExtensions; delete res.userData.gltfExtensions; res.userData = ThreeSerialization.Deserialize(res.userData, {}); res.userData.gltfExtensions = gltfExtensions; } return res; }; const tempPathDrc = generateUUID() + '.drc'; const tempPathKtx2 = generateUUID() + '.ktx2'; const needsDrc = parser.json?.extensionsRequired?.includes?.('KHR_draco_mesh_compression'); if (needsDrc) { const drc = viewer.assetManager.importer.registerFile(tempPathDrc); drc && this.setDRACOLoader(drc); // todo: check class? } const needsMeshOpt = parser.json?.extensionsUsed?.includes?.('EXT_meshopt_compression'); if (needsMeshOpt) { if (window.MeshoptDecoder) { // added by the plugin or by the user this.setMeshoptDecoder(window.MeshoptDecoder); parser.options.meshoptDecoder = window.MeshoptDecoder; } else { console.error('Add GLTFMeshOptPlugin(and initialize it) to viewer to enable EXT_meshopt_compression decode'); } } const needsBasisU = parser.json?.extensionsUsed?.includes?.('KHR_texture_basisu'); if (needsBasisU) { const ktx2 = viewer.assetManager.importer.registerFile(tempPathKtx2); if (ktx2) { this.setKTX2Loader(ktx2); // todo: check class? parser.options.ktx2Loader = ktx2; } } return { name: 'GLTF2_HELPER_PLUGIN', afterRoot: async (result) => { if (needsDrc) viewer.assetManager.importer.unregisterFile(tempPathDrc); if (needsBasisU) viewer.assetManager.importer.unregisterFile(tempPathKtx2); await GLTFViewerConfigExtension.ImportViewerConfig(parser, viewer, result.scenes || [result.scene]); } }; }; }; this.preparsers.push(glbEncryptionPreparser); GLTFLoader.ObjectConstructors.DirectionalLight = DirectionalLight2; GLTFLoader.ObjectConstructors.PointLight = PointLight2; GLTFLoader.ObjectConstructors.SpotLight = SpotLight2; GLTFLoader.ObjectConstructors.MeshStandardMaterial = PhysicalMaterial; GLTFLoader.ObjectConstructors.MeshBasicMaterial = UnlitMaterial; GLTFLoader.ObjectConstructors.MeshPhysicalMaterial = PhysicalMaterial; GLTFLoader.ObjectConstructors.LineBasicMaterial = UnlitLineMaterial; // GLTFLoader.ObjectConstructors.PointsMaterial = PointsMaterial2 GLTFLoader.ObjectConstructors.PerspectiveCamera = PerspectiveCamera0; // todo set domElement in the AssetManager during process GLTFLoader.ObjectConstructors.OrthographicCamera = OrthographicCamera; // todo } async preparse(data, path) { for (const preparser of this.preparsers) { data = await preparser.process(data, path); } return data; } parse(data, path, onLoad, onError, url) { this.preparse.call(this, data, url || path) .then((res) => res ? super.parse(res, path, onLoad, onError) : onError && onError(new ErrorEvent('no data'))) .catch((e) => { console.error(e); if (onError) onError(e ?? new ErrorEvent('unknown error')); }); } /** * This is run post parse to extract the result scene from the GLTF object * @param res * @param _ */ transform(res, _) { // todo: support loading of multiple scenes? const scene = res ? res.scene || !!res.scenes && res.scenes.length > 0 && res.scenes[0] : undefined; if (!scene) return undefined; if (res.animations.length > 0) scene.animations = res.animations; scene.traverse((node) => { if (node.userData.gltfUUID) { // saved in GLTFExporter2 safeSetProperty(node, 'uuid', node.userData.gltfUUID, true, true); delete node.userData.gltfUUID; // have issue with cloning if we don't dispose. } }); // todo: replacing lights and camera, todo: remove and change constructors in GLTFLoader.js if (!scene.userData) scene.userData = {}; if (res.userData) scene.userData.gltfExtras = res.userData; // todo: put back in gltf in GLTFExporter2 if (res.cameras) res.cameras.forEach(c => !c.parent && scene.add(c)); if (res.asset) scene.userData.gltfAsset = res.asset; // todo: put back in gltf in GLTFExporter2 return scene; } register(callback) { return super.register(callback); } setup(viewer, extraExtensions) { this.register(GLTFMaterialExtrasExtension.Import(viewer.loadConfigResources)); for (const ext of extraExtensions) this.register(ext); for (const ext of GLTFLoader2.ImportExtensions) this.register(ext); // Note: this should be last this.register(this.gltfViewerParser(viewer)); return this; } } GLTFLoader2.ImportExtensions = [ GLTFObject3DExtrasExtension.Import, GLTFLightExtrasExtension.Import, GLTFMaterialsBumpMapExtension.Import, GLTFMaterialsDisplacementMapExtension.Import, GLTFMaterialsLightMapExtension.Import, GLTFMaterialsAlphaMapExtension.Import, ]; //# sourceMappingURL=GLTFLoader2.js.map