UNPKG

@google/model-viewer

Version:

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

178 lines 7.48 kB
/* @license * Copyright 2019 Google LLC. 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, _b; import { Cache, EventDispatcher, GammaEncoding, NearestFilter, RGBEEncoding, TextureLoader } from 'three'; import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js'; import { PMREMGenerator } from './PMREMGenerator.js'; // Enable three's loader cache so we don't create redundant // Image objects to decode images fetched over the network. Cache.enabled = true; const HDR_FILE_RE = /\.hdr$/; const ldrLoader = new TextureLoader(); const hdrLoader = new RGBELoader(); const $environmentMapCache = Symbol('environmentMapCache'); const $generatedEnvironmentMap = Symbol('generatedEnvironmentMap'); const $PMREMGenerator = Symbol('PMREMGenerator'); const $addMetadata = Symbol('addMetadata'); const $loadEnvironmentMapFromUrl = Symbol('loadEnvironmentMapFromUrl'); const $loadGeneratedEnvironmentMap = Symbol('loadGeneratedEnvironmentMap'); // Attach a `userData` object for arbitrary data on textures that // originate from TextureUtils, similar to Object3D's userData, // for help debugging, providing metadata for tests, and semantically // describe the type of texture within the context of this application. const userData = { url: null, // 'Equirectangular', 'CubeUV', 'PMREM' mapping: null, }; export default class TextureUtils extends EventDispatcher { constructor(renderer) { super(); this[_a] = null; this[_b] = new Map(); this.renderer = renderer; this[$PMREMGenerator] = new PMREMGenerator(this.renderer); } async load(url, progressCallback = () => { }) { try { const isHDR = HDR_FILE_RE.test(url); const loader = isHDR ? hdrLoader : ldrLoader; const texture = await new Promise((resolve, reject) => loader.load(url, resolve, (event) => { progressCallback(event.loaded / event.total * 0.9); }, reject)); progressCallback(1.0); this[$addMetadata](texture, url, 'Equirectangular'); if (isHDR) { texture.encoding = RGBEEncoding; texture.minFilter = NearestFilter; texture.magFilter = NearestFilter; texture.flipY = true; } else { texture.encoding = GammaEncoding; } return texture; } finally { if (progressCallback) { progressCallback(1); } } } async loadEquirectAsCubeUV(url, progressCallback = () => { }) { let equirect = null; try { equirect = await this.load(url, progressCallback); const cubeUV = this[$PMREMGenerator].fromEquirectangular(equirect); this[$addMetadata](cubeUV.texture, url, 'CubeUV'); return cubeUV; } finally { if (equirect != null) { equirect.dispose(); } } } /** * Returns a { skybox, environmentMap } object with the targets/textures * accordingly. `skybox` is a WebGLRenderCubeTarget, and `environmentMap` * is a Texture from a WebGLRenderCubeTarget. */ async generateEnvironmentMapAndSkybox(skyboxUrl = null, environmentMapUrl = null, options = {}) { const { progressTracker } = options; const updateGenerationProgress = progressTracker != null ? progressTracker.beginActivity() : () => { }; try { let skyboxLoads = Promise.resolve(null); let environmentMapLoads; // If we have a skybox URL, attempt to load it as a cubemap if (!!skyboxUrl) { skyboxLoads = this[$loadEnvironmentMapFromUrl](skyboxUrl, progressTracker); } if (!!environmentMapUrl) { // We have an available environment map URL environmentMapLoads = this[$loadEnvironmentMapFromUrl](environmentMapUrl, progressTracker); } else if (!!skyboxUrl) { // Fallback to deriving the environment map from an available skybox environmentMapLoads = skyboxLoads; } else { // Fallback to generating the environment map environmentMapLoads = this[$loadGeneratedEnvironmentMap](); } let [environmentMap, skybox] = await Promise.all([environmentMapLoads, skyboxLoads]); this[$addMetadata](environmentMap.texture, environmentMapUrl, 'PMREM'); if (skybox != null) { this[$addMetadata](skybox.texture, skyboxUrl, 'PMREM'); } return { environmentMap, skybox }; } finally { updateGenerationProgress(1.0); } } [(_a = $generatedEnvironmentMap, _b = $environmentMapCache, $addMetadata)](texture, url, mapping) { texture.userData = Object.assign({}, userData, ({ url: url, mapping: mapping, })); } /** * Loads a WebGLRenderTarget from a given URL. The render target in this * case will be assumed to be used as an environment map. */ [$loadEnvironmentMapFromUrl](url, progressTracker) { if (!this[$environmentMapCache].has(url)) { const progressCallback = progressTracker ? progressTracker.beginActivity() : () => { }; const environmentMapLoads = this.loadEquirectAsCubeUV(url, progressCallback); this[$environmentMapCache].set(url, environmentMapLoads); } return this[$environmentMapCache].get(url); } /** * Loads a dynamically generated environment map. */ [$loadGeneratedEnvironmentMap]() { if (this[$generatedEnvironmentMap] == null) { this[$generatedEnvironmentMap] = this[$PMREMGenerator].fromDefault(); } return Promise.resolve(this[$generatedEnvironmentMap]); } async dispose() { const allTargetsLoad = []; // NOTE(cdata): We would use for-of iteration on the maps here, but // IE11 doesn't have the necessary iterator-returning methods. So, // disposal of these render targets is kind of convoluted as a result. this[$environmentMapCache].forEach((targetLoads) => { allTargetsLoad.push(targetLoads); }); this[$environmentMapCache].clear(); for (const targetLoads of allTargetsLoad) { try { const target = await targetLoads; target.dispose(); } catch (e) { // Suppress errors, so that all render targets will be disposed } } if (this[$generatedEnvironmentMap] != null) { this[$generatedEnvironmentMap].dispose(); this[$generatedEnvironmentMap] = null; } } } //# sourceMappingURL=TextureUtils.js.map