UNPKG

polygonjs-engine

Version:

node-based webgl 3D engine https://polygonjs.com

246 lines (245 loc) 8.76 kB
import {VideoTexture as VideoTexture2} from "three/src/textures/VideoTexture"; import {TextureLoader as TextureLoader2} from "three/src/loaders/TextureLoader"; import {UnsignedByteType} from "three/src/constants"; import {CoreWalker} from "../Walker"; import {BaseCopNodeClass} from "../../engine/nodes/cop/_Base"; import {Poly as Poly2} from "../../engine/Poly"; import {ModuleName} from "../../engine/poly/registers/modules/_BaseRegister"; import {CoreUserAgent} from "../UserAgent"; var Extension; (function(Extension2) { Extension2["EXR"] = "exr"; Extension2["BASIS"] = "basis"; Extension2["HDR"] = "hdr"; })(Extension || (Extension = {})); const CoreTextureLoader2 = class { constructor(_node, _param) { this._node = _node; this._param = _param; } async load_texture_from_url_or_op(url) { let texture = null; let found_node; if (url.substring(0, 3) == "op:") { const node_path = url.substring(3); found_node = CoreWalker.find_node(this._node, node_path); if (found_node) { if (found_node instanceof BaseCopNodeClass) { const container = await found_node.requestContainer(); texture = container.texture(); } else { this._node.states.error.set(`found node is not a texture node`); } } else { this._node.states.error.set(`no node found in path '${node_path}'`); } } else { texture = await this.load_url(url); if (texture) { if (this._param.options.texture_as_env()) { } else { texture = CoreTextureLoader2.set_texture_for_mapping(texture); } } else { this._node.states.error.set(`could not load texture ${url}`); } } if (found_node && this._param.graphPredecessors()[0] != found_node) { this._param.graphDisconnectPredecessors(); this._param.addGraphInput(found_node); } return texture; } async load_url(url) { return new Promise(async (resolve, reject) => { const ext = CoreTextureLoader2.get_extension(url); if (url[0] != "h") { const assets_root = this._node.scene().assets.root(); if (assets_root) { url = `${assets_root}${url}`; } } if (CoreTextureLoader2.VIDEO_EXTENSIONS.includes(ext)) { const texture = await this._load_as_video(url); resolve(texture); } else { this.loader_for_ext(ext).then(async (loader) => { if (loader) { CoreTextureLoader2.increment_in_progress_loads_count(); await CoreTextureLoader2.wait_for_max_concurrent_loads_queue_freed(); loader.load(url, (texture) => { CoreTextureLoader2.decrement_in_progress_loads_count(); resolve(texture); }, void 0, (error) => { CoreTextureLoader2.decrement_in_progress_loads_count(); Poly2.warn("error", error); reject(); }); } else { reject(); } }); } }); } static module_names(ext) { switch (ext) { case Extension.EXR: return [ModuleName.EXRLoader]; case Extension.HDR: return [ModuleName.RGBELoader]; case Extension.BASIS: return [ModuleName.BasisTextureLoader]; } } async loader_for_ext(ext) { const ext_lowercase = ext.toLowerCase(); switch (ext_lowercase) { case Extension.EXR: { return await this._exr_loader(); } case Extension.HDR: { return await this._hdr_loader(); } case Extension.BASIS: { return await this._basis_loader(); } } return new TextureLoader2(); } async _exr_loader() { const module = await Poly2.modulesRegister.module(ModuleName.EXRLoader); if (module) { return new module.EXRLoader(); } } async _hdr_loader() { const module = await Poly2.modulesRegister.module(ModuleName.RGBELoader); if (module) { const loader = new module.RGBELoader(); loader.setDataType(UnsignedByteType); return loader; } } async _basis_loader() { const module = await Poly2.modulesRegister.module(ModuleName.BasisTextureLoader); if (module) { const loader = new module.BasisTextureLoader(); loader.setTranscoderPath("/three/js/libs/basis/"); const renderer = await Poly2.renderersController.waitForRenderer(); if (renderer) { loader.detectSupport(renderer); } else { Poly2.warn("texture loader found no renderer for basis texture loader"); } return loader; } } _load_as_video(url) { return new Promise((resolve, reject) => { const video = document.createElement("video"); video.setAttribute("crossOrigin", "anonymous"); video.setAttribute("autoplay", `${true}`); video.setAttribute("loop", `${true}`); video.onloadedmetadata = function() { video.pause(); const texture = new VideoTexture2(video); resolve(texture); }; const original_source = document.createElement("source"); const original_ext = CoreTextureLoader2.get_extension(url); let type = CoreTextureLoader2.VIDEO_SOURCE_TYPE_BY_EXT[original_ext]; type = type || CoreTextureLoader2._default_video_source_type(url); original_source.setAttribute("type", type); original_source.setAttribute("src", url); video.appendChild(original_source); let secondary_url = url; if (original_ext == "mp4") { secondary_url = CoreTextureLoader2.replace_extension(url, "ogv"); } else { secondary_url = CoreTextureLoader2.replace_extension(url, "mp4"); } const secondary_source = document.createElement("source"); const secondary_ext = CoreTextureLoader2.get_extension(secondary_url); type = CoreTextureLoader2.VIDEO_SOURCE_TYPE_BY_EXT[secondary_ext]; type = type || CoreTextureLoader2._default_video_source_type(url); secondary_source.setAttribute("type", type); secondary_source.setAttribute("src", url); video.appendChild(secondary_source); }); } static _default_video_source_type(url) { const ext = this.get_extension(url); return `video/${ext}`; } static pixel_data(texture) { const img = texture.image; const canvas = document.createElement("canvas"); canvas.width = img.width; canvas.height = img.height; const context = canvas.getContext("2d"); if (context) { context.drawImage(img, 0, 0, img.width, img.height); return context.getImageData(0, 0, img.width, img.height); } } static get_extension(url) { const elements = url.split("."); return elements[elements.length - 1].toLowerCase(); } static replace_extension(url, new_extension) { const elements = url.split("?"); const url_without_params = elements[0]; const url_elements = url_without_params.split("."); url_elements.pop(); url_elements.push(new_extension); return [url_elements.join("."), elements[1]].join("?"); } static set_texture_for_mapping(texture) { return texture; } static _init_max_concurrent_loads_count() { return CoreUserAgent.is_chrome() ? 10 : 4; } static _init_concurrent_loads_delay() { return CoreUserAgent.is_chrome() ? 0 : 10; } static override_max_concurrent_loads_count(count) { this.MAX_CONCURRENT_LOADS_COUNT = count; } static increment_in_progress_loads_count() { this.in_progress_loads_count++; } static decrement_in_progress_loads_count() { this.in_progress_loads_count--; const queued_resolve = this._queue.pop(); if (queued_resolve) { const delay = this.CONCURRENT_LOADS_DELAY; setTimeout(() => { queued_resolve(); }, delay); } } static async wait_for_max_concurrent_loads_queue_freed() { if (this.in_progress_loads_count <= this.MAX_CONCURRENT_LOADS_COUNT) { return; } else { return new Promise((resolve) => { this._queue.push(resolve); }); } } }; export let CoreTextureLoader = CoreTextureLoader2; CoreTextureLoader.PARAM_DEFAULT = "/examples/textures/uv.jpg"; CoreTextureLoader.PARAM_ENV_DEFAULT = "/examples/textures/piz_compressed.exr"; CoreTextureLoader.VIDEO_EXTENSIONS = ["mp4", "webm", "ogv"]; CoreTextureLoader.VIDEO_SOURCE_TYPE_BY_EXT = { ogg: 'video/ogg; codecs="theora, vorbis"', ogv: 'video/ogg; codecs="theora, vorbis"', mp4: 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"' }; CoreTextureLoader.MAX_CONCURRENT_LOADS_COUNT = CoreTextureLoader2._init_max_concurrent_loads_count(); CoreTextureLoader.CONCURRENT_LOADS_DELAY = CoreTextureLoader2._init_concurrent_loads_delay(); CoreTextureLoader.in_progress_loads_count = 0; CoreTextureLoader._queue = [];