UNPKG

@google/model-viewer

Version:

Easily display interactive 3D models on the web and in AR!

139 lines 5.18 kB
/* * Copyright 2019 Google Inc. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the 'License'); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an 'AS IS' BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ var _a; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'; import { CacheEvictionPolicy } from '../utilities/cache-eviction-policy.js'; import { cloneGltf } from './ModelUtils.js'; export const loadWithLoader = (url, loader, progressCallback = () => { }) => { const onProgress = (event) => { progressCallback(event.loaded / event.total); }; return new Promise((resolve, reject) => { loader.load(url, resolve, onProgress, reject); }); }; export const $releaseFromCache = Symbol('releaseFromCache'); const cache = new Map(); const preloaded = new Map(); export const $evictionPolicy = Symbol('evictionPolicy'); export class CachingGLTFLoader { constructor() { this.loader = new GLTFLoader(); } static get cache() { return cache; } static clearCache() { cache.forEach((_value, url) => { this.delete(url); }); this[$evictionPolicy].reset(); } static has(url) { return cache.has(url); } static async delete(url) { if (!this.has(url)) { return; } const gltfLoads = cache.get(url); preloaded.delete(url); cache.delete(url); const gltf = await gltfLoads; // Dispose of the cached glTF's materials and geometries: gltf.scenes.forEach(scene => { scene.traverse(object3D => { if (!object3D.isMesh) { return; } const mesh = object3D; const materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material]; materials.forEach(material => { material.dispose(); }); mesh.geometry.dispose(); }); }); } /** * Returns true if the model that corresponds to the specified url is * available in our local cache. */ static hasFinishedLoading(url) { return !!preloaded.get(url); } get [(_a = $evictionPolicy, $evictionPolicy)]() { return this.constructor[$evictionPolicy]; } /** * Preloads a glTF, populating the cache. Returns a promise that resolves * when the cache is populated. */ async preload(url, progressCallback = () => { }) { if (!cache.has(url)) { cache.set(url, loadWithLoader(url, this.loader, (progress) => { progressCallback(progress * 0.9); })); } await cache.get(url); if (progressCallback) { progressCallback(1.0); } preloaded.set(url, true); } /** * Loads a glTF from the specified url and resolves a unique clone of the * glTF. If the glTF has already been loaded, makes a clone of the cached * copy. */ async load(url, progressCallback = () => { }) { await this.preload(url, progressCallback); const gltf = cloneGltf(await cache.get(url)); const model = gltf.scene ? gltf.scene : null; if (model != null) { model.userData.animations = gltf.animations; // save animations this[$evictionPolicy].retain(url); model[$releaseFromCache] = (() => { let released = false; return () => { if (released) { return; } // We manually dispose cloned materials because Three.js keeps // an internal count of materials using the same program, so it's // safe to dispose of them incrementally. Geometry clones are not // accounted for, so they cannot be disposed of incrementally. model.traverse((object3D) => { if (!object3D.isMesh) { return; } const mesh = object3D; const materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material]; materials.forEach(material => { material.dispose(); }); }); this[$evictionPolicy].release(url); released = true; }; })(); } return model; } } CachingGLTFLoader[_a] = new CacheEvictionPolicy(CachingGLTFLoader); self.CachingGLTFLoader = CachingGLTFLoader; self.$evictionPolicy = $evictionPolicy; //# sourceMappingURL=CachingGLTFLoader.js.map