UNPKG

@photo-sphere-viewer/cubemap-video-adapter

Version:
236 lines (229 loc) 7.31 kB
/*! * Photo Sphere Viewer / Cubemap Video Adapter 5.15.0 * @copyright 2015-2026 Damien "Mistic" Sorel * @licence MIT (https://opensource.org/licenses/MIT) */ // src/CubemapVideoAdapter.ts import { CONSTANTS, utils } from "@photo-sphere-viewer/core"; import { BoxGeometry, Mesh as Mesh2, ShaderMaterial, Vector2 } from "three"; // ../shared/AbstractVideoAdapter.ts import { AbstractAdapter, PSVError } from "@photo-sphere-viewer/core"; import { VideoTexture } from "three"; // ../shared/video-utils.ts function createVideo({ src, withCredentials, muted, autoplay }) { const video = document.createElement("video"); video.crossOrigin = withCredentials ? "use-credentials" : "anonymous"; video.loop = true; video.playsInline = true; video.autoplay = autoplay; video.muted = muted; video.preload = "metadata"; if (src instanceof MediaStream) { video.srcObject = src; } else { video.src = src; } return video; } // ../shared/AbstractVideoAdapter.ts var AbstractVideoAdapter = class extends AbstractAdapter { constructor(viewer) { super(viewer); } init() { super.init(); this.viewer.needsContinuousUpdate(true); } destroy() { this.__removeVideo(); super.destroy(); } supportsPreload() { return false; } supportsTransition() { return false; } async loadTexture(panorama) { if (typeof panorama !== "object" || !panorama.source) { return Promise.reject(new PSVError("Invalid panorama configuration, are you using the right adapter?")); } if (!this.viewer.getPlugin("video")) { return Promise.reject(new PSVError("Video adapters require VideoPlugin to be loaded too.")); } const video = panorama.source instanceof HTMLVideoElement ? panorama.source : createVideo({ src: panorama.source, withCredentials: this.viewer.config.withCredentials(panorama.source), muted: true, autoplay: false }); await this.__videoLoadPromise(video); const texture = new VideoTexture(video); return { panorama, texture }; } switchVideo(texture) { let currentTime; let duration; let paused = !this.config.autoplay; let muted = this.config.muted; let volume = 1; if (this.video) { ({ currentTime, duration, paused, muted, volume } = this.video); } this.__removeVideo(); this.video = texture.image; if (this.video.duration === duration) { this.video.currentTime = currentTime; } this.video.muted = muted; this.video.volume = volume; if (!paused) { this.video.play(); } } setTextureOpacity() { } disposeTexture({ texture }) { texture.dispose(); } disposeMesh(mesh) { mesh.geometry.dispose(); mesh.material.dispose(); } __removeVideo() { if (this.video) { this.video.pause(); this.video.remove(); delete this.video; } } __videoLoadPromise(video) { return new Promise((resolve, reject) => { const onLoaded = () => { if (this.video && video.duration === this.video.duration) { video.currentTime = this.video.currentTime; } resolve(); video.removeEventListener("loadedmetadata", onLoaded); }; const onError = (err) => { reject(err); video.removeEventListener("error", onError); }; video.addEventListener("loadedmetadata", onLoaded); video.addEventListener("error", onError); }); } }; AbstractVideoAdapter.supportsDownload = false; // src/shaders/equiangular.fragment.glsl var equiangular_fragment_default = "// shamelessly copied from https://github.com/videojs/videojs-vr/blob/main/src/plugin.js\n\nvarying vec2 vUv;\nuniform sampler2D map;\nuniform bool equiangular;\nuniform float contCorrect;\nuniform vec2 faceWH;\nuniform vec2 vidWH;\n\nconst float PI = 3.1415926535897932384626433832795;\n\nvoid main() {\n vec2 corner = vUv - mod(vUv, faceWH) + vec2(0, contCorrect / vidWH.y);\n vec2 faceWHadj = faceWH - vec2(0, contCorrect * 2. / vidWH.y);\n vec2 p = (vUv - corner) / faceWHadj - .5;\n vec2 q = equiangular ? 2. / PI * atan(2. * p) + .5 : p + .5;\n vec2 eUv = corner + q * faceWHadj;\n gl_FragColor = texture2D(map, eUv);\n}\n"; // src/shaders/equiangular.vertex.glsl var equiangular_vertex_default = "varying vec2 vUv;\n\nvoid main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}\n"; // src/CubemapVideoAdapter.ts var getConfig = utils.getConfigParser({ autoplay: false, muted: false }); var _CubemapVideoAdapter = class _CubemapVideoAdapter extends AbstractVideoAdapter { static withConfig(config) { return [_CubemapVideoAdapter, config]; } constructor(viewer, config) { super(viewer); this.config = getConfig(config); } async loadTexture(panorama) { const { texture } = await super.loadTexture(panorama); const panoData = { isCubemap: true, equiangular: panorama.equiangular ?? true }; return { panorama, texture, panoData }; } createMesh(panoData) { const cubeSize = CONSTANTS.SPHERE_RADIUS * 2; const geometry = new BoxGeometry(cubeSize, cubeSize, cubeSize).scale(1, 1, -1).toNonIndexed(); this.__setUVs(geometry); const material = new ShaderMaterial({ uniforms: { map: { value: null }, equiangular: { value: panoData.equiangular }, contCorrect: { value: 1 }, faceWH: { value: new Vector2(1 / 3, 1 / 2) }, vidWH: { value: new Vector2(1, 1) } }, vertexShader: equiangular_vertex_default, fragmentShader: equiangular_fragment_default, depthTest: false, depthWrite: false }); return new Mesh2(geometry, material); } setTexture(mesh, { texture }) { const video = texture.image; const uniforms = mesh.material.uniforms; uniforms.map.value = texture; uniforms.vidWH.value.set(video.videoWidth, video.videoHeight); this.switchVideo(texture); } __setUVs(geometry) { geometry.clearGroups(); const uvs = geometry.getAttribute("uv"); const a = 0; const b = 1 / 3; const c = 2 / 3; const d = 1; const A = 1; const B = 1 / 2; const C = 0; uvs.setXY(0, a, A); uvs.setXY(1, a, B); uvs.setXY(2, b, A); uvs.setXY(3, a, B); uvs.setXY(4, b, B); uvs.setXY(5, b, A); uvs.setXY(6, c, A); uvs.setXY(7, c, B); uvs.setXY(8, d, A); uvs.setXY(9, c, B); uvs.setXY(10, d, B); uvs.setXY(11, d, A); uvs.setXY(12, d, B); uvs.setXY(13, c, B); uvs.setXY(14, d, C); uvs.setXY(15, c, B); uvs.setXY(16, c, C); uvs.setXY(17, d, C); uvs.setXY(18, b, B); uvs.setXY(19, a, B); uvs.setXY(20, b, C); uvs.setXY(21, a, B); uvs.setXY(22, a, C); uvs.setXY(23, b, C); uvs.setXY(24, c, B); uvs.setXY(25, b, B); uvs.setXY(26, c, C); uvs.setXY(27, b, B); uvs.setXY(28, b, C); uvs.setXY(29, c, C); uvs.setXY(30, b, A); uvs.setXY(31, b, B); uvs.setXY(32, c, A); uvs.setXY(33, b, B); uvs.setXY(34, c, B); uvs.setXY(35, c, A); } }; _CubemapVideoAdapter.id = "cubemap-video"; _CubemapVideoAdapter.VERSION = "5.15.0"; var CubemapVideoAdapter = _CubemapVideoAdapter; export { CubemapVideoAdapter }; //# sourceMappingURL=index.module.js.map