From c78efbfac61172bb11b72646c85918c87b7958ea Mon Sep 17 00:00:00 2001 From: trichu Date: Tue, 9 May 2023 10:41:21 -0700 Subject: [PATCH 1/2] add three.js multiview patch --- patches/super-three+0.147.1.patch | 2340 ++++++++++++++++++++++++++++- 1 file changed, 2296 insertions(+), 44 deletions(-) diff --git a/patches/super-three+0.147.1.patch b/patches/super-three+0.147.1.patch index 0cf63736091..371ff38c5e3 100644 --- a/patches/super-three+0.147.1.patch +++ b/patches/super-three+0.147.1.patch @@ -1,47 +1,2299 @@ +diff --git a/node_modules/super-three/build/three.cjs b/node_modules/super-three/build/three.cjs +index 3bd7eaf..23ffd5c 100644 +--- a/node_modules/super-three/build/three.cjs ++++ b/node_modules/super-three/build/three.cjs +@@ -10715,7 +10715,7 @@ function WebGLBackground(renderer, cubemaps, cubeuvmaps, state, objects, alpha, + + if (background && (background.isCubeTexture || background.mapping === CubeUVReflectionMapping)) { + if (boxMesh === undefined) { +- boxMesh = new Mesh(new BoxGeometry(1, 1, 1), new ShaderMaterial({ ++ boxMesh = new Mesh(new BoxGeometry(10000, 10000, 10000), new ShaderMaterial({ + name: 'BackgroundCubeMaterial', + uniforms: cloneUniforms(ShaderLib.backgroundCube.uniforms), + vertexShader: ShaderLib.backgroundCube.vertexShader, +@@ -14170,6 +14170,7 @@ function WebGLProgram(renderer, cacheKey, parameters, bindingStates) { + const program = gl.createProgram(); + let prefixVertex, prefixFragment; + let versionString = parameters.glslVersion ? '#version ' + parameters.glslVersion + '\n' : ''; ++ var numMultiviewViews = parameters.numMultiviewViews; + + if (parameters.isRawShaderMaterial) { + prefixVertex = [customDefines].filter(filterEmptyLine).join('\n'); +@@ -14204,6 +14205,14 @@ function WebGLProgram(renderer, cacheKey, parameters, bindingStates) { + versionString = '#version 300 es\n'; + prefixVertex = ['precision mediump sampler2DArray;', '#define attribute in', '#define varying out', '#define texture2D texture'].join('\n') + '\n' + prefixVertex; + prefixFragment = ['#define varying in', parameters.glslVersion === GLSL3 ? '' : 'layout(location = 0) out highp vec4 pc_fragColor;', parameters.glslVersion === GLSL3 ? '' : '#define gl_FragColor pc_fragColor', '#define gl_FragDepthEXT gl_FragDepth', '#define texture2D texture', '#define textureCube texture', '#define texture2DProj textureProj', '#define texture2DLodEXT textureLod', '#define texture2DProjLodEXT textureProjLod', '#define textureCubeLodEXT textureLod', '#define texture2DGradEXT textureGrad', '#define texture2DProjGradEXT textureProjGrad', '#define textureCubeGradEXT textureGrad'].join('\n') + '\n' + prefixFragment; ++ ++ // Multiview ++ if (numMultiviewViews > 0) { ++ prefixVertex = ['#extension GL_OVR_multiview : require', 'layout(num_views = ' + numMultiviewViews + ') in;', '#define VIEW_ID gl_ViewID_OVR'].join('\n') + '\n' + prefixVertex; ++ prefixVertex = prefixVertex.replace(['uniform mat4 modelViewMatrix;', 'uniform mat4 projectionMatrix;', 'uniform mat4 viewMatrix;', 'uniform mat3 normalMatrix;'].join('\n'), ['uniform mat4 modelViewMatrices[' + numMultiviewViews + '];', 'uniform mat4 projectionMatrices[' + numMultiviewViews + '];', 'uniform mat4 viewMatrices[' + numMultiviewViews + '];', 'uniform mat3 normalMatrices[' + numMultiviewViews + '];', '#define modelViewMatrix modelViewMatrices[VIEW_ID]', '#define projectionMatrix projectionMatrices[VIEW_ID]', '#define viewMatrix viewMatrices[VIEW_ID]', '#define normalMatrix normalMatrices[VIEW_ID]'].join('\n')); ++ prefixFragment = ['#extension GL_OVR_multiview : require', '#define VIEW_ID gl_ViewID_OVR'].join('\n') + '\n' + prefixFragment; ++ prefixFragment = prefixFragment.replace('uniform mat4 viewMatrix;', ['uniform mat4 viewMatrices[' + numMultiviewViews + '];', '#define viewMatrix viewMatrices[VIEW_ID]'].join('\n')); ++ } + } + + const vertexGlsl = versionString + prefixVertex + vertexShader; +@@ -14301,6 +14310,7 @@ function WebGLProgram(renderer, cacheKey, parameters, bindingStates) { + this.program = program; + this.vertexShader = glVertexShader; + this.fragmentShader = glFragmentShader; ++ this.numMultiviewViews = numMultiviewViews; + return this; + } + +@@ -14466,6 +14476,7 @@ function WebGLPrograms(renderer, cubemaps, cubeuvmaps, extensions, capabilities, + } + + const currentRenderTarget = renderer.getRenderTarget(); ++ const numMultiviewViews = currentRenderTarget && currentRenderTarget.isWebGLMultiviewRenderTarget ? currentRenderTarget.numViews : 0; + const useAlphaTest = material.alphaTest > 0; + const useClearcoat = material.clearcoat > 0; + const useIridescence = material.iridescence > 0; +@@ -14484,6 +14495,7 @@ function WebGLPrograms(renderer, cubemaps, cubeuvmaps, extensions, capabilities, + instancing: object.isInstancedMesh === true, + instancingColor: object.isInstancedMesh === true && object.instanceColor !== null, + supportsVertexTextures: vertexTextures, ++ numMultiviewViews: numMultiviewViews, + outputEncoding: currentRenderTarget === null ? renderer.outputEncoding : currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.encoding : LinearEncoding, + map: !!material.map, + matcap: !!material.matcap, +@@ -14694,6 +14706,7 @@ function WebGLPrograms(renderer, cubemaps, cubeuvmaps, extensions, capabilities, + if (parameters.sheenRoughnessMap) _programLayers.enable(22); + if (parameters.decodeVideoTexture) _programLayers.enable(23); + if (parameters.opaque) _programLayers.enable(24); ++ if (parameters.numMultiviewViews) _programLayers.enable(25); + array.push(_programLayers.mask); + } + +@@ -16637,12 +16650,16 @@ function WebGLTextures(_gl, extensions, state, properties, capabilities, utils, + const maxSamples = capabilities.maxSamples; + const multisampledRTTExt = extensions.has('WEBGL_multisampled_render_to_texture') ? extensions.get('WEBGL_multisampled_render_to_texture') : null; + const supportsInvalidateFramebuffer = typeof navigator === 'undefined' ? false : /OculusBrowser/g.test(navigator.userAgent); ++ const multiviewExt = extensions.has('OCULUS_multiview') ? extensions.get('OCULUS_multiview') : null; + + const _videoTextures = new WeakMap(); + + let _canvas; + + const _sources = new WeakMap(); // maps WebglTexture objects to instances of Source ++ ++ let _deferredUploads = []; ++ + // cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas, + // also OffscreenCanvas.getContext("webgl"), but not OffscreenCanvas.getContext("2d")! + // Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d). +@@ -16934,8 +16951,9 @@ function WebGLTextures(_gl, extensions, state, properties, capabilities, utils, + } else if (image.complete === false) { + console.warn('THREE.WebGLRenderer: Texture marked for update but image is incomplete'); + } else { +- uploadTexture(textureProperties, texture, slot); +- return; ++ if (this.uploadTexture(textureProperties, texture, slot)) { ++ return; ++ } + } + } + +@@ -16946,7 +16964,7 @@ function WebGLTextures(_gl, extensions, state, properties, capabilities, utils, + const textureProperties = properties.get(texture); + + if (texture.version > 0 && textureProperties.__version !== texture.version) { +- uploadTexture(textureProperties, texture, slot); ++ this.uploadTexture(textureProperties, texture, slot); + return; + } + +@@ -16957,7 +16975,7 @@ function WebGLTextures(_gl, extensions, state, properties, capabilities, utils, + const textureProperties = properties.get(texture); + + if (texture.version > 0 && textureProperties.__version !== texture.version) { +- uploadTexture(textureProperties, texture, slot); ++ this.uploadTexture(textureProperties, texture, slot); + return; + } + +@@ -16995,7 +17013,7 @@ function WebGLTextures(_gl, extensions, state, properties, capabilities, utils, + + _gl.texParameteri(textureType, _gl.TEXTURE_WRAP_T, wrappingToGL[texture.wrapT]); + +- if (textureType === _gl.TEXTURE_3D || textureType === _gl.TEXTURE_2D_ARRAY) { ++ if ((textureType === _gl.TEXTURE_3D || textureType === _gl.TEXTURE_2D_ARRAY) && texture.wrapR !== undefined) { + _gl.texParameteri(textureType, _gl.TEXTURE_WRAP_R, wrappingToGL[texture.wrapR]); + } + +@@ -17095,7 +17113,29 @@ function WebGLTextures(_gl, extensions, state, properties, capabilities, utils, + return forceUpload; + } + ++ function runDeferredUploads() { ++ const previousDeferSetting = this.deferTextureUploads; ++ this.deferTextureUploads = false; ++ for (const upload of _deferredUploads) { ++ this.uploadTexture(upload.textureProperties, upload.texture, upload.slot); ++ upload.texture.isPendingDeferredUpload = false; ++ } ++ _deferredUploads = []; ++ this.deferTextureUploads = previousDeferSetting; ++ } ++ + function uploadTexture(textureProperties, texture, slot) { ++ if (this.deferTextureUploads) { ++ if (!texture.isPendingDeferredUpload) { ++ texture.isPendingDeferredUpload = true; ++ _deferredUploads.push({ ++ textureProperties: textureProperties, ++ texture: texture, ++ slot: slot ++ }); ++ } ++ return false; ++ } + let textureType = _gl.TEXTURE_2D; + if (texture.isDataArrayTexture || texture.isCompressedArrayTexture) textureType = _gl.TEXTURE_2D_ARRAY; + if (texture.isData3DTexture) textureType = _gl.TEXTURE_3D; +@@ -17346,6 +17386,7 @@ function WebGLTextures(_gl, extensions, state, properties, capabilities, utils, + } + + textureProperties.__version = texture.version; ++ return true; + } + + function uploadCubeTexture(textureProperties, texture, slot) { +@@ -17491,7 +17532,9 @@ function WebGLTextures(_gl, extensions, state, properties, capabilities, utils, + const renderTargetProperties = properties.get(renderTarget); + + if (!renderTargetProperties.__hasExternalTextures) { +- if (textureTarget === _gl.TEXTURE_3D || textureTarget === _gl.TEXTURE_2D_ARRAY) { ++ if (renderTarget.isWebGLMultiviewRenderTarget === true) { ++ state.texStorage3D(_gl.TEXTURE_2D_ARRAY, 0, glInternalFormat, renderTarget.width, renderTarget.height, renderTarget.numViews); ++ } else if (textureTarget === _gl.TEXTURE_3D || textureTarget === _gl.TEXTURE_2D_ARRAY) { + state.texImage3D(textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, renderTarget.depth, 0, glFormat, glType, null); + } else { + state.texImage2D(textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null); +@@ -17500,11 +17543,21 @@ function WebGLTextures(_gl, extensions, state, properties, capabilities, utils, + + state.bindFramebuffer(_gl.FRAMEBUFFER, framebuffer); + +- if (useMultisampledRTT(renderTarget)) { +- multisampledRTTExt.framebufferTexture2DMultisampleEXT(_gl.FRAMEBUFFER, attachment, textureTarget, properties.get(texture).__webglTexture, 0, getRenderTargetSamples(renderTarget)); ++ const multisampled = useMultisampledRTT(renderTarget); ++ if (renderTarget.isWebGLMultiviewRenderTarget === true) { ++ if (multisampled) { ++ multiviewExt.framebufferTextureMultisampleMultiviewOVR(_gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, properties.get(texture).__webglTexture, 0, getRenderTargetSamples(renderTarget), 0, renderTarget.numViews); ++ } else { ++ multiviewExt.framebufferTextureMultiviewOVR(_gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, properties.get(texture).__webglTexture, 0, 0, renderTarget.numViews); ++ } + } else if (textureTarget === _gl.TEXTURE_2D || textureTarget >= _gl.TEXTURE_CUBE_MAP_POSITIVE_X && textureTarget <= _gl.TEXTURE_CUBE_MAP_NEGATIVE_Z) { + // see #24753 +- _gl.framebufferTexture2D(_gl.FRAMEBUFFER, attachment, textureTarget, properties.get(texture).__webglTexture, 0); ++ ++ if (multisampled) { ++ multisampledRTTExt.framebufferTexture2DMultisampleEXT(_gl.FRAMEBUFFER, attachment, textureTarget, properties.get(texture).__webglTexture, 0, getRenderTargetSamples(renderTarget)); ++ } else { ++ _gl.framebufferTexture2D(_gl.FRAMEBUFFER, attachment, textureTarget, properties.get(texture).__webglTexture, 0); ++ } + } + + state.bindFramebuffer(_gl.FRAMEBUFFER, null); +@@ -17514,7 +17567,42 @@ function WebGLTextures(_gl, extensions, state, properties, capabilities, utils, + function setupRenderBufferStorage(renderbuffer, renderTarget, isMultisample) { + _gl.bindRenderbuffer(_gl.RENDERBUFFER, renderbuffer); + +- if (renderTarget.depthBuffer && !renderTarget.stencilBuffer) { ++ if (renderTarget.isWebGLMultiviewRenderTarget === true) { ++ const useMultisample = useMultisampledRTT(renderTarget); ++ const numViews = renderTarget.numViews; ++ const depthTexture = renderTarget.depthTexture; ++ let glInternalFormat = _gl.DEPTH_COMPONENT24; ++ let glDepthAttachment = _gl.DEPTH_ATTACHMENT; ++ if (depthTexture && depthTexture.isDepthTexture) { ++ if (depthTexture.type === FloatType) { ++ glInternalFormat = _gl.DEPTH_COMPONENT32F; ++ } else if (depthTexture.type === UnsignedInt248Type) { ++ glInternalFormat = _gl.DEPTH24_STENCIL8; ++ glDepthAttachment = _gl.DEPTH_STENCIL_ATTACHMENT; ++ } ++ ++ // we're defaulting to _gl.DEPTH_COMPONENT24 so don't assign here ++ // or else DeepScan will complain ++ ++ // else if ( depthTexture.type === UnsignedIntType ) { ++ ++ // glInternalFormat = _gl.DEPTH_COMPONENT24; ++ ++ // } ++ } ++ ++ let depthStencilTexture = properties.get(renderTarget.depthTexture).__webglTexture; ++ if (depthStencilTexture === undefined) { ++ depthStencilTexture = _gl.createTexture(); ++ _gl.bindTexture(_gl.TEXTURE_2D_ARRAY, depthStencilTexture); ++ _gl.texStorage3D(_gl.TEXTURE_2D_ARRAY, 1, glInternalFormat, renderTarget.width, renderTarget.height, numViews); ++ } ++ if (useMultisample) { ++ multiviewExt.framebufferTextureMultisampleMultiviewOVR(_gl.FRAMEBUFFER, glDepthAttachment, depthStencilTexture, 0, getRenderTargetSamples(renderTarget), 0, numViews); ++ } else { ++ multiviewExt.framebufferTextureMultiviewOVR(_gl.FRAMEBUFFER, glDepthAttachment, depthStencilTexture, 0, 0, numViews); ++ } ++ } else if (renderTarget.depthBuffer && !renderTarget.stencilBuffer) { + let glInternalFormat = _gl.DEPTH_COMPONENT16; + + if (isMultisample || useMultisampledRTT(renderTarget)) { +@@ -17592,26 +17680,50 @@ function WebGLTextures(_gl, extensions, state, properties, capabilities, utils, + renderTarget.depthTexture.needsUpdate = true; + } + +- setTexture2D(renderTarget.depthTexture, 0); ++ if (renderTarget.depthTexture.image.depth != 1) { ++ this.setTexture2DArray(renderTarget.depthTexture, 0); ++ } else { ++ this.setTexture2D(renderTarget.depthTexture, 0); ++ } + + const webglDepthTexture = properties.get(renderTarget.depthTexture).__webglTexture; + + const samples = getRenderTargetSamples(renderTarget); + +- if (renderTarget.depthTexture.format === DepthFormat) { +- if (useMultisampledRTT(renderTarget)) { +- multisampledRTTExt.framebufferTexture2DMultisampleEXT(_gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples); ++ if (renderTarget.isWebGLMultiviewRenderTarget === true) { ++ const useMultisample = useMultisampledRTT(renderTarget); ++ const numViews = renderTarget.numViews; ++ if (renderTarget.depthTexture.format === DepthFormat) { ++ if (useMultisample) { ++ multiviewExt.framebufferTextureMultisampleMultiviewOVR(_gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, webglDepthTexture, 0, samples, 0, numViews); ++ } else { ++ multiviewExt.framebufferTextureMultiviewOVR(_gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, webglDepthTexture, 0, 0, numViews); ++ } ++ } else if (renderTarget.depthTexture.format === DepthStencilFormat) { ++ if (useMultisample) { ++ multiviewExt.framebufferTextureMultisampleMultiviewOVR(_gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, webglDepthTexture, 0, samples, 0, numViews); ++ } else { ++ multiviewExt.framebufferTextureMultiviewOVR(_gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, webglDepthTexture, 0, 0, numViews); ++ } + } else { +- _gl.framebufferTexture2D(_gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0); ++ throw new Error('Unknown depthTexture format'); + } +- } else if (renderTarget.depthTexture.format === DepthStencilFormat) { +- if (useMultisampledRTT(renderTarget)) { +- multisampledRTTExt.framebufferTexture2DMultisampleEXT(_gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples); ++ } else { ++ if (renderTarget.depthTexture.format === DepthFormat) { ++ if (useMultisampledRTT(renderTarget)) { ++ multisampledRTTExt.framebufferTexture2DMultisampleEXT(_gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples); ++ } else { ++ _gl.framebufferTexture2D(_gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0); ++ } ++ } else if (renderTarget.depthTexture.format === DepthStencilFormat) { ++ if (useMultisampledRTT(renderTarget)) { ++ multisampledRTTExt.framebufferTexture2DMultisampleEXT(_gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples); ++ } else { ++ _gl.framebufferTexture2D(_gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0); ++ } + } else { +- _gl.framebufferTexture2D(_gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0); ++ throw new Error('Unknown depthTexture format'); + } +- } else { +- throw new Error('Unknown depthTexture format'); + } + } // Setup GL resources for a non-texture depth buffer + +@@ -17622,7 +17734,7 @@ function WebGLTextures(_gl, extensions, state, properties, capabilities, utils, + + if (renderTarget.depthTexture && !renderTargetProperties.__autoAllocateDepthBuffer) { + if (isCube) throw new Error('target.depthTexture not supported in Cube render targets'); +- setupDepthTexture(renderTargetProperties.__webglFramebuffer, renderTarget); ++ this.setupDepthTexture(renderTargetProperties.__webglFramebuffer, renderTarget); + } else { + if (isCube) { + renderTargetProperties.__webglDepthbuffer = []; +@@ -17640,22 +17752,20 @@ function WebGLTextures(_gl, extensions, state, properties, capabilities, utils, + } + + state.bindFramebuffer(_gl.FRAMEBUFFER, null); +- } // rebind framebuffer with external textures +- ++ } + ++ // rebind framebuffer with external textures + function rebindTextures(renderTarget, colorTexture, depthTexture) { + const renderTargetProperties = properties.get(renderTarget); +- + if (colorTexture !== undefined) { +- setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer, renderTarget, renderTarget.texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D); ++ this.setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer, renderTarget, renderTarget.texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D); + } +- + if (depthTexture !== undefined) { +- setupDepthRenderbuffer(renderTarget); ++ this.setupDepthRenderbuffer(renderTarget); + } +- } // Set up GL resources for the render target +- ++ } + ++ // Set up GL resources for the render target + function setupRenderTarget(renderTarget) { + const texture = renderTarget.texture; + const renderTargetProperties = properties.get(renderTarget); +@@ -17775,6 +17885,9 @@ function WebGLTextures(_gl, extensions, state, properties, capabilities, utils, + } + } + ++ if (renderTarget.isWebGLMultiviewRenderTarget === true) { ++ glTextureType = _gl.TEXTURE_2D_ARRAY; ++ } + state.bindTexture(glTextureType, textureProperties.__webglTexture); + setTextureParameters(glTextureType, texture, supportsMips); + setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer, renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType); +@@ -17787,8 +17900,8 @@ function WebGLTextures(_gl, extensions, state, properties, capabilities, utils, + } // Setup depth and stencil buffers + + +- if (renderTarget.depthBuffer) { +- setupDepthRenderbuffer(renderTarget); ++ if (renderTarget.depthBuffer || renderTarget.isWebGLMultiviewRenderTarget === true) { ++ this.setupDepthRenderbuffer(renderTarget); + } + } + +@@ -17956,12 +18069,15 @@ function WebGLTextures(_gl, extensions, state, properties, capabilities, utils, + this.setTexture3D = setTexture3D; + this.setTextureCube = setTextureCube; + this.rebindTextures = rebindTextures; ++ this.uploadTexture = uploadTexture; + this.setupRenderTarget = setupRenderTarget; + this.updateRenderTargetMipmap = updateRenderTargetMipmap; + this.updateMultisampleRenderTarget = updateMultisampleRenderTarget; ++ this.setupDepthTexture = setupDepthTexture; + this.setupDepthRenderbuffer = setupDepthRenderbuffer; + this.setupFrameBufferTexture = setupFrameBufferTexture; + this.useMultisampledRTT = useMultisampledRTT; ++ this.runDeferredUploads = runDeferredUploads; + } + + function WebGLUtils(gl, extensions, capabilities) { +@@ -18139,6 +18255,64 @@ function WebGLUtils(gl, extensions, capabilities) { + }; + } + ++ ++/** ++ * @author fernandojsg / http://fernandojsg.com ++ * @author Takahiro https://github.com/takahirox ++ */ ++class WebGLMultiview { ++ constructor(renderer, extensions, gl) { ++ this.renderer = renderer; ++ this.DEFAULT_NUMVIEWS = 2; ++ this.maxNumViews = 0; ++ this.gl = gl; ++ this.extensions = extensions; ++ this.available = this.extensions.has('OCULUS_multiview'); ++ if (this.available) { ++ const extension = this.extensions.get('OCULUS_multiview'); ++ this.maxNumViews = this.gl.getParameter(extension.MAX_VIEWS_OVR); ++ this.mat4 = []; ++ this.mat3 = []; ++ this.cameraArray = []; ++ for (var i = 0; i < this.maxNumViews; i++) { ++ this.mat4[i] = new Matrix4(); ++ this.mat3[i] = new Matrix3(); ++ } ++ } ++ } ++ ++ // ++ getCameraArray(camera) { ++ if (camera.isArrayCamera) return camera.cameras; ++ this.cameraArray[0] = camera; ++ return this.cameraArray; ++ } ++ updateCameraProjectionMatricesUniform(camera, uniforms) { ++ var cameras = this.getCameraArray(camera); ++ for (var i = 0; i < cameras.length; i++) { ++ this.mat4[i].copy(cameras[i].projectionMatrix); ++ } ++ uniforms.setValue(this.gl, 'projectionMatrices', this.mat4); ++ } ++ updateCameraViewMatricesUniform(camera, uniforms) { ++ var cameras = this.getCameraArray(camera); ++ for (var i = 0; i < cameras.length; i++) { ++ this.mat4[i].copy(cameras[i].matrixWorldInverse); ++ } ++ uniforms.setValue(this.gl, 'viewMatrices', this.mat4); ++ } ++ updateObjectMatricesUniforms(object, camera, uniforms) { ++ var cameras = this.getCameraArray(camera); ++ for (var i = 0; i < cameras.length; i++) { ++ this.mat4[i].multiplyMatrices(cameras[i].matrixWorldInverse, object.matrixWorld); ++ this.mat3[i].getNormalMatrix(this.mat4[i]); ++ } ++ uniforms.setValue(this.gl, 'modelViewMatrices', this.mat4); ++ uniforms.setValue(this.gl, 'normalMatrices', this.mat3); ++ } ++} ++ ++ + class Group extends Object3D { + constructor() { + super(); +@@ -18538,6 +18712,26 @@ Object.assign(WebVRManager.prototype, { + dispatchEvent: EventDispatcher.prototype.dispatchEvent + }); + ++/** ++ * @author fernandojsg / http://fernandojsg.com ++ * @author Takahiro https://github.com/takahirox ++ */ ++class WebGLMultiviewRenderTarget extends WebGLRenderTarget { ++ constructor(width, height, numViews, options = {}) { ++ super(width, height, options); ++ this.depthBuffer = false; ++ this.stencilBuffer = false; ++ this.numViews = numViews; ++ } ++ copy(source) { ++ super.copy(source); ++ this.numViews = source.numViews; ++ return this; ++ } ++} ++WebGLMultiviewRenderTarget.prototype.isWebGLMultiviewRenderTarget = true; ++ ++ + const _moveEvent = { + type: 'move' + }; +@@ -18807,7 +19001,7 @@ class DepthTexture extends Texture { + } + + class WebXRManager extends EventDispatcher { +- constructor(renderer, gl) { ++ constructor(renderer, gl, extensions, useMultiview) { + super(); + const scope = this; + let session = null; +@@ -18847,7 +19041,7 @@ class WebXRManager extends EventDispatcher { + this.layersEnabled = false; + this.enabled = false; + this.isPresenting = false; +- ++ this.isMultiview = false; + this.getCameraPose = function () { + return pose; + }; +@@ -19023,25 +19217,35 @@ class WebXRManager extends EventDispatcher { + depthFormat = attributes.stencil ? DepthStencilFormat : DepthFormat; + depthType = attributes.stencil ? UnsignedInt248Type : UnsignedIntType; + } +- ++ scope.isMultiview = useMultiview && extensions.has('OCULUS_multiview'); + const projectionlayerInit = { + colorFormat: gl.RGBA8, + depthFormat: glDepthFormat, + scaleFactor: framebufferScaleFactor + }; ++ if (scope.isMultiview) { ++ projectionlayerInit.textureType = 'texture-array'; ++ } + glBinding = new XRWebGLBinding(session, gl); + glProjLayer = glBinding.createProjectionLayer(projectionlayerInit); + session.updateRenderState({ + layers: [glProjLayer] + }); +- newRenderTarget = new WebGLRenderTarget(glProjLayer.textureWidth, glProjLayer.textureHeight, { ++ const rtOptions = { + format: RGBAFormat, + type: UnsignedByteType, + depthTexture: new DepthTexture(glProjLayer.textureWidth, glProjLayer.textureHeight, depthType, undefined, undefined, undefined, undefined, undefined, undefined, depthFormat), + stencilBuffer: attributes.stencil, + encoding: renderer.outputEncoding, + samples: attributes.antialias ? 4 : 0 +- }); ++ }; ++ if (scope.isMultiview) { ++ const extension = extensions.get('OCULUS_multiview'); ++ this.maxNumViews = gl.getParameter(extension.MAX_VIEWS_OVR); ++ newRenderTarget = new WebGLMultiviewRenderTarget(glProjLayer.textureWidth, glProjLayer.textureHeight, 2, rtOptions); ++ } else { ++ newRenderTarget = new WebGLRenderTarget(glProjLayer.textureWidth, glProjLayer.textureHeight, rtOptions); ++ } + const renderTargetProperties = renderer.properties.get(newRenderTarget); + renderTargetProperties.__ignoreDepthValues = glProjLayer.ignoreDepthValues; + } +@@ -20119,7 +20323,8 @@ function WebGLRenderer(parameters = {}) { + _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true, + _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false, + _powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default', +- _failIfMajorPerformanceCaveat = parameters.failIfMajorPerformanceCaveat !== undefined ? parameters.failIfMajorPerformanceCaveat : false; ++ _failIfMajorPerformanceCaveat = parameters.failIfMajorPerformanceCaveat !== undefined ? parameters.failIfMajorPerformanceCaveat : false, ++ _multiviewStereo = parameters.multiviewStereo !== undefined ? parameters.multiviewStereo : false; + + let _alpha; + +@@ -20290,6 +20495,7 @@ function WebGLRenderer(parameters = {}) { + let extensions, capabilities, state, info; + let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects; + let programCache, materials, renderLists, renderStates, clipping, shadowMap; ++ let multiview; + let background, morphtargets, bufferRenderer, indexedBufferRenderer; + let utils, bindingStates, uniformsGroups; + +@@ -20311,6 +20517,7 @@ function WebGLRenderer(parameters = {}) { + morphtargets = new WebGLMorphtargets(_gl, capabilities, textures); + clipping = new WebGLClipping(properties); + programCache = new WebGLPrograms(_this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping); ++ multiview = new WebGLMultiview(_this, extensions, _gl); + materials = new WebGLMaterials(_this, properties); + renderLists = new WebGLRenderLists(); + renderStates = new WebGLRenderStates(extensions, capabilities); +@@ -20330,7 +20537,7 @@ function WebGLRenderer(parameters = {}) { + } + + initGLContext(); +- const xr = typeof navigator !== 'undefined' && 'xr' in navigator ? new WebXRManager(_this, _gl) : new WebVRManager(_this); ++ const xr = typeof navigator !== 'undefined' && 'xr' in navigator ? new WebXRManager(_this, _gl, extensions, _multiviewStereo) : new WebVRManager(_this); + this.xr = xr; // API + + this.getContext = function () { +@@ -20781,11 +20988,16 @@ function WebGLRenderer(parameters = {}) { + currentRenderState.setupLights(_this.physicallyCorrectLights); + + if (camera.isArrayCamera) { +- const cameras = camera.cameras; ++ if (xr.enabled && xr.isMultiview) { ++ textures.deferTextureUploads = true; ++ renderScene(currentRenderList, scene, camera, camera.cameras[0].viewport); ++ } else { ++ const cameras = camera.cameras; + +- for (let i = 0, l = cameras.length; i < l; i++) { +- const camera2 = cameras[i]; +- renderScene(currentRenderList, scene, camera2, camera2.viewport); ++ for (let i = 0, l = cameras.length; i < l; i++) { ++ const camera2 = cameras[i]; ++ renderScene(currentRenderList, scene, camera2, camera2.viewport); ++ } + } + } else { + renderScene(currentRenderList, scene, camera); +@@ -20804,7 +21016,10 @@ function WebGLRenderer(parameters = {}) { + + if (xr.enabled && xr.submitFrame) { + xr.submitFrame(); +- } // _gl.finish(); ++ } ++ ++ textures.runDeferredUploads(); ++ // _gl.finish(); + + + bindingStates.resetDefaultState(); +@@ -21088,6 +21303,7 @@ function WebGLRenderer(parameters = {}) { + materialProperties.vertexAlphas = parameters.vertexAlphas; + materialProperties.vertexTangents = parameters.vertexTangents; + materialProperties.toneMapping = parameters.toneMapping; ++ materialProperties.numMultiviewViews = parameters.numMultiviewViews; + } + + function setProgram(camera, scene, geometry, material, object) { +@@ -21104,6 +21320,7 @@ function WebGLRenderer(parameters = {}) { + const morphNormals = !!geometry.morphAttributes.normal; + const morphColors = !!geometry.morphAttributes.color; + const toneMapping = material.toneMapped ? _this.toneMapping : NoToneMapping; ++ const numMultiviewViews = _currentRenderTarget && _currentRenderTarget.isWebGLMultiviewRenderTarget ? _currentRenderTarget.numViews : 0; + const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; + const morphTargetsCount = morphAttribute !== undefined ? morphAttribute.length : 0; + const materialProperties = properties.get(material); +@@ -21155,6 +21372,8 @@ function WebGLRenderer(parameters = {}) { + needsProgramChange = true; + } else if (capabilities.isWebGL2 === true && materialProperties.morphTargetsCount !== morphTargetsCount) { + needsProgramChange = true; ++ } else if (materialProperties.numMultiviewViews !== numMultiviewViews) { ++ needsProgramChange = true; + } + } else { + needsProgramChange = true; +@@ -21186,7 +21405,11 @@ function WebGLRenderer(parameters = {}) { + } + + if (refreshProgram || _currentCamera !== camera) { +- p_uniforms.setValue(_gl, 'projectionMatrix', camera.projectionMatrix); ++ if (program.numMultiviewViews > 0) { ++ multiview.updateCameraProjectionMatricesUniform(camera, p_uniforms); ++ } else { ++ p_uniforms.setValue(_gl, 'projectionMatrix', camera.projectionMatrix); ++ } + + if (capabilities.logarithmicDepthBuffer) { + p_uniforms.setValue(_gl, 'logDepthBufFC', 2.0 / (Math.log(camera.far + 1.0) / Math.LN2)); +@@ -21217,7 +21440,11 @@ function WebGLRenderer(parameters = {}) { + } + + if (material.isMeshPhongMaterial || material.isMeshToonMaterial || material.isMeshLambertMaterial || material.isMeshBasicMaterial || material.isMeshStandardMaterial || material.isShaderMaterial || material.isShadowMaterial || object.isSkinnedMesh) { +- p_uniforms.setValue(_gl, 'viewMatrix', camera.matrixWorldInverse); ++ if (program.numMultiviewViews > 0) { ++ multiview.updateCameraViewMatricesUniform(camera, p_uniforms); ++ } else { ++ p_uniforms.setValue(_gl, 'viewMatrix', camera.matrixWorldInverse); ++ } + } + } // skinning and morph target uniforms must be set even if material didn't change + // auto-setting of texture unit for bone and morph texture must go before other textures +@@ -21290,8 +21517,12 @@ function WebGLRenderer(parameters = {}) { + } // common matrices + + +- p_uniforms.setValue(_gl, 'modelViewMatrix', object.modelViewMatrix); +- p_uniforms.setValue(_gl, 'normalMatrix', object.normalMatrix); ++ if (program.numMultiviewViews > 0) { ++ multiview.updateObjectMatricesUniforms(object, camera, p_uniforms); ++ } else { ++ p_uniforms.setValue(_gl, 'modelViewMatrix', object.modelViewMatrix); ++ p_uniforms.setValue(_gl, 'normalMatrix', object.normalMatrix); ++ } + p_uniforms.setValue(_gl, 'modelMatrix', object.matrixWorld); // UBOs + + if (material.isShaderMaterial || material.isRawShaderMaterial) { +@@ -21364,18 +21595,17 @@ function WebGLRenderer(parameters = {}) { + const renderTargetProperties = properties.get(renderTarget); + renderTargetProperties.__hasExternalTextures = true; + +- if (renderTargetProperties.__hasExternalTextures) { +- renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === undefined; ++ renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === undefined; + +- if (!renderTargetProperties.__autoAllocateDepthBuffer) { +- // The multisample_render_to_texture extension doesn't work properly if there +- // are midframe flushes and an external depth buffer. Disable use of the extension. +- if (extensions.has('WEBGL_multisampled_render_to_texture') === true) { +- console.warn('THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided'); +- renderTargetProperties.__useRenderToTexture = false; +- } ++ if (!renderTargetProperties.__autoAllocateDepthBuffer && !_currentRenderTarget.isWebGLMultiviewRenderTarget) { ++ // The multisample_render_to_texture extension doesn't work properly if there ++ // are midframe flushes and an external depth buffer. Disable use of the extension. ++ if (extensions.has('WEBGL_multisampled_render_to_texture') === true) { ++ console.warn('THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided'); ++ renderTargetProperties.__useRenderToTexture = false; + } + } ++ + }; + + this.setRenderTargetFramebuffer = function (renderTarget, defaultFramebuffer) { +diff --git a/node_modules/super-three/build/three.js b/node_modules/super-three/build/three.js +index 76cc32d..063a626 100644 +--- a/node_modules/super-three/build/three.js ++++ b/node_modules/super-three/build/three.js +@@ -10717,7 +10717,7 @@ + + if (background && (background.isCubeTexture || background.mapping === CubeUVReflectionMapping)) { + if (boxMesh === undefined) { +- boxMesh = new Mesh(new BoxGeometry(1, 1, 1), new ShaderMaterial({ ++ boxMesh = new Mesh(new BoxGeometry(10000, 10000, 10000), new ShaderMaterial({ + name: 'BackgroundCubeMaterial', + uniforms: cloneUniforms(ShaderLib.backgroundCube.uniforms), + vertexShader: ShaderLib.backgroundCube.vertexShader, +@@ -14172,6 +14172,7 @@ + const program = gl.createProgram(); + let prefixVertex, prefixFragment; + let versionString = parameters.glslVersion ? '#version ' + parameters.glslVersion + '\n' : ''; ++ var numMultiviewViews = parameters.numMultiviewViews; + + if (parameters.isRawShaderMaterial) { + prefixVertex = [customDefines].filter(filterEmptyLine).join('\n'); +@@ -14206,6 +14207,15 @@ + versionString = '#version 300 es\n'; + prefixVertex = ['precision mediump sampler2DArray;', '#define attribute in', '#define varying out', '#define texture2D texture'].join('\n') + '\n' + prefixVertex; + prefixFragment = ['#define varying in', parameters.glslVersion === GLSL3 ? '' : 'layout(location = 0) out highp vec4 pc_fragColor;', parameters.glslVersion === GLSL3 ? '' : '#define gl_FragColor pc_fragColor', '#define gl_FragDepthEXT gl_FragDepth', '#define texture2D texture', '#define textureCube texture', '#define texture2DProj textureProj', '#define texture2DLodEXT textureLod', '#define texture2DProjLodEXT textureProjLod', '#define textureCubeLodEXT textureLod', '#define texture2DGradEXT textureGrad', '#define texture2DProjGradEXT textureProjGrad', '#define textureCubeGradEXT textureGrad'].join('\n') + '\n' + prefixFragment; ++ ++ // Multiview ++ if (numMultiviewViews > 0) { ++ prefixVertex = ['#extension GL_OVR_multiview : require', 'layout(num_views = ' + numMultiviewViews + ') in;', '#define VIEW_ID gl_ViewID_OVR'].join('\n') + '\n' + prefixVertex; ++ prefixVertex = prefixVertex.replace(['uniform mat4 modelViewMatrix;', 'uniform mat4 projectionMatrix;', 'uniform mat4 viewMatrix;', 'uniform mat3 normalMatrix;'].join('\n'), ['uniform mat4 modelViewMatrices[' + numMultiviewViews + '];', 'uniform mat4 projectionMatrices[' + numMultiviewViews + '];', 'uniform mat4 viewMatrices[' + numMultiviewViews + '];', 'uniform mat3 normalMatrices[' + numMultiviewViews + '];', '#define modelViewMatrix modelViewMatrices[VIEW_ID]', '#define projectionMatrix projectionMatrices[VIEW_ID]', '#define viewMatrix viewMatrices[VIEW_ID]', '#define normalMatrix normalMatrices[VIEW_ID]'].join('\n')); ++ prefixFragment = ['#extension GL_OVR_multiview : require', '#define VIEW_ID gl_ViewID_OVR'].join('\n') + '\n' + prefixFragment; ++ prefixFragment = prefixFragment.replace('uniform mat4 viewMatrix;', ['uniform mat4 viewMatrices[' + numMultiviewViews + '];', '#define viewMatrix viewMatrices[VIEW_ID]'].join('\n')); ++ } ++ } + } + + const vertexGlsl = versionString + prefixVertex + vertexShader; +@@ -14303,6 +14313,7 @@ + this.program = program; + this.vertexShader = glVertexShader; + this.fragmentShader = glFragmentShader; ++ this.numMultiviewViews = numMultiviewViews; + return this; + } + +@@ -14468,6 +14479,7 @@ + } + + const currentRenderTarget = renderer.getRenderTarget(); ++ const numMultiviewViews = currentRenderTarget && currentRenderTarget.isWebGLMultiviewRenderTarget ? currentRenderTarget.numViews : 0; + const useAlphaTest = material.alphaTest > 0; + const useClearcoat = material.clearcoat > 0; + const useIridescence = material.iridescence > 0; +@@ -14486,6 +14498,7 @@ + instancing: object.isInstancedMesh === true, + instancingColor: object.isInstancedMesh === true && object.instanceColor !== null, + supportsVertexTextures: vertexTextures, ++ numMultiviewViews: numMultiviewViews, + outputEncoding: currentRenderTarget === null ? renderer.outputEncoding : currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.encoding : LinearEncoding, + map: !!material.map, + matcap: !!material.matcap, +@@ -14696,6 +14709,7 @@ + if (parameters.sheenRoughnessMap) _programLayers.enable(22); + if (parameters.decodeVideoTexture) _programLayers.enable(23); + if (parameters.opaque) _programLayers.enable(24); ++ if (parameters.numMultiviewViews) _programLayers.enable(25); + array.push(_programLayers.mask); + } + +@@ -16639,12 +16653,14 @@ + const maxSamples = capabilities.maxSamples; + const multisampledRTTExt = extensions.has('WEBGL_multisampled_render_to_texture') ? extensions.get('WEBGL_multisampled_render_to_texture') : null; + const supportsInvalidateFramebuffer = typeof navigator === 'undefined' ? false : /OculusBrowser/g.test(navigator.userAgent); ++ const multiviewExt = extensions.has('OCULUS_multiview') ? extensions.get('OCULUS_multiview') : null; + + const _videoTextures = new WeakMap(); + + let _canvas; + + const _sources = new WeakMap(); // maps WebglTexture objects to instances of Source ++ let _deferredUploads = []; + // cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas, + // also OffscreenCanvas.getContext("webgl"), but not OffscreenCanvas.getContext("2d")! + // Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d). +@@ -16936,8 +16952,9 @@ + } else if (image.complete === false) { + console.warn('THREE.WebGLRenderer: Texture marked for update but image is incomplete'); + } else { +- uploadTexture(textureProperties, texture, slot); +- return; ++ if (this.uploadTexture(textureProperties, texture, slot)) { ++ return; ++ } + } + } + +@@ -16948,7 +16965,7 @@ + const textureProperties = properties.get(texture); + + if (texture.version > 0 && textureProperties.__version !== texture.version) { +- uploadTexture(textureProperties, texture, slot); ++ this.uploadTexture(textureProperties, texture, slot); + return; + } + +@@ -16959,7 +16976,7 @@ + const textureProperties = properties.get(texture); + + if (texture.version > 0 && textureProperties.__version !== texture.version) { +- uploadTexture(textureProperties, texture, slot); ++ this.uploadTexture(textureProperties, texture, slot); + return; + } + +@@ -16997,7 +17014,7 @@ + + _gl.texParameteri(textureType, _gl.TEXTURE_WRAP_T, wrappingToGL[texture.wrapT]); + +- if (textureType === _gl.TEXTURE_3D || textureType === _gl.TEXTURE_2D_ARRAY) { ++ if ((textureType === _gl.TEXTURE_3D || textureType === _gl.TEXTURE_2D_ARRAY) && texture.wrapR !== undefined) { + _gl.texParameteri(textureType, _gl.TEXTURE_WRAP_R, wrappingToGL[texture.wrapR]); + } + +@@ -17097,7 +17114,29 @@ + return forceUpload; + } + ++ function runDeferredUploads() { ++ const previousDeferSetting = this.deferTextureUploads; ++ this.deferTextureUploads = false; ++ for (const upload of _deferredUploads) { ++ this.uploadTexture(upload.textureProperties, upload.texture, upload.slot); ++ upload.texture.isPendingDeferredUpload = false; ++ } ++ _deferredUploads = []; ++ this.deferTextureUploads = previousDeferSetting; ++ } ++ + function uploadTexture(textureProperties, texture, slot) { ++ if (this.deferTextureUploads) { ++ if (!texture.isPendingDeferredUpload) { ++ texture.isPendingDeferredUpload = true; ++ _deferredUploads.push({ ++ textureProperties: textureProperties, ++ texture: texture, ++ slot: slot ++ }); ++ } ++ return false; ++ } + let textureType = _gl.TEXTURE_2D; + if (texture.isDataArrayTexture || texture.isCompressedArrayTexture) textureType = _gl.TEXTURE_2D_ARRAY; + if (texture.isData3DTexture) textureType = _gl.TEXTURE_3D; +@@ -17348,6 +17387,7 @@ + } + + textureProperties.__version = texture.version; ++ return true; + } + + function uploadCubeTexture(textureProperties, texture, slot) { +@@ -17493,20 +17533,30 @@ + const renderTargetProperties = properties.get(renderTarget); + + if (!renderTargetProperties.__hasExternalTextures) { +- if (textureTarget === _gl.TEXTURE_3D || textureTarget === _gl.TEXTURE_2D_ARRAY) { ++ if (renderTarget.isWebGLMultiviewRenderTarget === true) { ++ state.texStorage3D(_gl.TEXTURE_2D_ARRAY, 0, glInternalFormat, renderTarget.width, renderTarget.height, renderTarget.numViews); ++ } else if (textureTarget === _gl.TEXTURE_3D || textureTarget === _gl.TEXTURE_2D_ARRAY) { + state.texImage3D(textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, renderTarget.depth, 0, glFormat, glType, null); + } else { + state.texImage2D(textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null); + } + } + +- state.bindFramebuffer(_gl.FRAMEBUFFER, framebuffer); ++ const multisampled = useMultisampledRTT(renderTarget); + +- if (useMultisampledRTT(renderTarget)) { +- multisampledRTTExt.framebufferTexture2DMultisampleEXT(_gl.FRAMEBUFFER, attachment, textureTarget, properties.get(texture).__webglTexture, 0, getRenderTargetSamples(renderTarget)); ++ if (renderTarget.isWebGLMultiviewRenderTarget === true) { ++ if (multisampled) { ++ multiviewExt.framebufferTextureMultisampleMultiviewOVR(_gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, properties.get(texture).__webglTexture, 0, getRenderTargetSamples(renderTarget), 0, renderTarget.numViews); ++ } else { ++ multiviewExt.framebufferTextureMultiviewOVR(_gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, properties.get(texture).__webglTexture, 0, 0, renderTarget.numViews); ++ } + } else if (textureTarget === _gl.TEXTURE_2D || textureTarget >= _gl.TEXTURE_CUBE_MAP_POSITIVE_X && textureTarget <= _gl.TEXTURE_CUBE_MAP_NEGATIVE_Z) { + // see #24753 +- _gl.framebufferTexture2D(_gl.FRAMEBUFFER, attachment, textureTarget, properties.get(texture).__webglTexture, 0); ++ if (multisampled) { ++ multisampledRTTExt.framebufferTexture2DMultisampleEXT(_gl.FRAMEBUFFER, attachment, textureTarget, properties.get(texture).__webglTexture, 0, getRenderTargetSamples(renderTarget)); ++ } else { ++ _gl.framebufferTexture2D(_gl.FRAMEBUFFER, attachment, textureTarget, properties.get(texture).__webglTexture, 0); ++ } + } + + state.bindFramebuffer(_gl.FRAMEBUFFER, null); +@@ -17516,7 +17566,42 @@ + function setupRenderBufferStorage(renderbuffer, renderTarget, isMultisample) { + _gl.bindRenderbuffer(_gl.RENDERBUFFER, renderbuffer); + +- if (renderTarget.depthBuffer && !renderTarget.stencilBuffer) { ++ if (renderTarget.isWebGLMultiviewRenderTarget === true) { ++ const useMultisample = useMultisampledRTT(renderTarget); ++ const numViews = renderTarget.numViews; ++ const depthTexture = renderTarget.depthTexture; ++ let glInternalFormat = _gl.DEPTH_COMPONENT24; ++ let glDepthAttachment = _gl.DEPTH_ATTACHMENT; ++ if (depthTexture && depthTexture.isDepthTexture) { ++ if (depthTexture.type === FloatType) { ++ glInternalFormat = _gl.DEPTH_COMPONENT32F; ++ } else if (depthTexture.type === UnsignedInt248Type) { ++ glInternalFormat = _gl.DEPTH24_STENCIL8; ++ glDepthAttachment = _gl.DEPTH_STENCIL_ATTACHMENT; ++ } ++ ++ // we're defaulting to _gl.DEPTH_COMPONENT24 so don't assign here ++ // or else DeepScan will complain ++ ++ // else if ( depthTexture.type === UnsignedIntType ) { ++ ++ // glInternalFormat = _gl.DEPTH_COMPONENT24; ++ ++ // } ++ } ++ ++ let depthStencilTexture = properties.get(renderTarget.depthTexture).__webglTexture; ++ if (depthStencilTexture === undefined) { ++ depthStencilTexture = _gl.createTexture(); ++ _gl.bindTexture(_gl.TEXTURE_2D_ARRAY, depthStencilTexture); ++ _gl.texStorage3D(_gl.TEXTURE_2D_ARRAY, 1, glInternalFormat, renderTarget.width, renderTarget.height, numViews); ++ } ++ if (useMultisample) { ++ multiviewExt.framebufferTextureMultisampleMultiviewOVR(_gl.FRAMEBUFFER, glDepthAttachment, depthStencilTexture, 0, getRenderTargetSamples(renderTarget), 0, numViews); ++ } else { ++ multiviewExt.framebufferTextureMultiviewOVR(_gl.FRAMEBUFFER, glDepthAttachment, depthStencilTexture, 0, 0, numViews); ++ } ++ } else if (renderTarget.depthBuffer && !renderTarget.stencilBuffer) { + let glInternalFormat = _gl.DEPTH_COMPONENT16; + + if (isMultisample || useMultisampledRTT(renderTarget)) { +@@ -17594,26 +17679,50 @@ + renderTarget.depthTexture.needsUpdate = true; + } + +- setTexture2D(renderTarget.depthTexture, 0); ++ if (renderTarget.depthTexture.image.depth != 1) { ++ this.setTexture2DArray(renderTarget.depthTexture, 0); ++ } else { ++ this.setTexture2D(renderTarget.depthTexture, 0); ++ } + + const webglDepthTexture = properties.get(renderTarget.depthTexture).__webglTexture; + + const samples = getRenderTargetSamples(renderTarget); + +- if (renderTarget.depthTexture.format === DepthFormat) { +- if (useMultisampledRTT(renderTarget)) { +- multisampledRTTExt.framebufferTexture2DMultisampleEXT(_gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples); ++ if (renderTarget.isWebGLMultiviewRenderTarget === true) { ++ const useMultisample = useMultisampledRTT(renderTarget); ++ const numViews = renderTarget.numViews; ++ if (renderTarget.depthTexture.format === DepthFormat) { ++ if (useMultisample) { ++ multiviewExt.framebufferTextureMultisampleMultiviewOVR(_gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, webglDepthTexture, 0, samples, 0, numViews); ++ } else { ++ multiviewExt.framebufferTextureMultiviewOVR(_gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, webglDepthTexture, 0, 0, numViews); ++ } ++ } else if (renderTarget.depthTexture.format === DepthStencilFormat) { ++ if (useMultisample) { ++ multiviewExt.framebufferTextureMultisampleMultiviewOVR(_gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, webglDepthTexture, 0, samples, 0, numViews); ++ } else { ++ multiviewExt.framebufferTextureMultiviewOVR(_gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, webglDepthTexture, 0, 0, numViews); ++ } + } else { +- _gl.framebufferTexture2D(_gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0); ++ throw new Error('Unknown depthTexture format'); + } +- } else if (renderTarget.depthTexture.format === DepthStencilFormat) { +- if (useMultisampledRTT(renderTarget)) { +- multisampledRTTExt.framebufferTexture2DMultisampleEXT(_gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples); ++ } else { ++ if (renderTarget.depthTexture.format === DepthFormat) { ++ if (useMultisampledRTT(renderTarget)) { ++ multisampledRTTExt.framebufferTexture2DMultisampleEXT(_gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples); ++ } else { ++ _gl.framebufferTexture2D(_gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0); ++ } ++ } else if (renderTarget.depthTexture.format === DepthStencilFormat) { ++ if (useMultisampledRTT(renderTarget)) { ++ multisampledRTTExt.framebufferTexture2DMultisampleEXT(_gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples); ++ } else { ++ _gl.framebufferTexture2D(_gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0); ++ } + } else { +- _gl.framebufferTexture2D(_gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0); ++ throw new Error('Unknown depthTexture format'); + } +- } else { +- throw new Error('Unknown depthTexture format'); + } + } // Setup GL resources for a non-texture depth buffer + +@@ -17624,7 +17733,7 @@ + + if (renderTarget.depthTexture && !renderTargetProperties.__autoAllocateDepthBuffer) { + if (isCube) throw new Error('target.depthTexture not supported in Cube render targets'); +- setupDepthTexture(renderTargetProperties.__webglFramebuffer, renderTarget); ++ this.setupDepthTexture(renderTargetProperties.__webglFramebuffer, renderTarget); + } else { + if (isCube) { + renderTargetProperties.__webglDepthbuffer = []; +@@ -17642,20 +17751,18 @@ + } + + state.bindFramebuffer(_gl.FRAMEBUFFER, null); +- } // rebind framebuffer with external textures +- ++ } + ++ // rebind framebuffer with external textures + function rebindTextures(renderTarget, colorTexture, depthTexture) { + const renderTargetProperties = properties.get(renderTarget); +- + if (colorTexture !== undefined) { +- setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer, renderTarget, renderTarget.texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D); ++ this.setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer, renderTarget, renderTarget.texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D); + } +- + if (depthTexture !== undefined) { +- setupDepthRenderbuffer(renderTarget); ++ this.setupDepthRenderbuffer(renderTarget); + } +- } // Set up GL resources for the render target ++ } + + + function setupRenderTarget(renderTarget) { +@@ -17777,6 +17884,10 @@ + } + } + ++ if (renderTarget.isWebGLMultiviewRenderTarget === true) { ++ glTextureType = _gl.TEXTURE_2D_ARRAY; ++ } ++ + state.bindTexture(glTextureType, textureProperties.__webglTexture); + setTextureParameters(glTextureType, texture, supportsMips); + setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer, renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType); +@@ -17789,8 +17900,8 @@ + } // Setup depth and stencil buffers + + +- if (renderTarget.depthBuffer) { +- setupDepthRenderbuffer(renderTarget); ++ if (renderTarget.depthBuffer || renderTarget.isWebGLMultiviewRenderTarget === true) { ++ this.setupDepthRenderbuffer(renderTarget); + } + } + +@@ -17958,12 +18069,15 @@ + this.setTexture3D = setTexture3D; + this.setTextureCube = setTextureCube; + this.rebindTextures = rebindTextures; ++ this.uploadTexture = uploadTexture; + this.setupRenderTarget = setupRenderTarget; + this.updateRenderTargetMipmap = updateRenderTargetMipmap; + this.updateMultisampleRenderTarget = updateMultisampleRenderTarget; ++ this.setupDepthTexture = setupDepthTexture; + this.setupDepthRenderbuffer = setupDepthRenderbuffer; + this.setupFrameBufferTexture = setupFrameBufferTexture; + this.useMultisampledRTT = useMultisampledRTT; ++ this.runDeferredUploads = runDeferredUploads; + } + + function WebGLUtils(gl, extensions, capabilities) { +@@ -18141,6 +18255,64 @@ + }; + } + ++ ++ /** ++ * @author fernandojsg / http://fernandojsg.com ++ * @author Takahiro https://github.com/takahirox ++ */ ++ class WebGLMultiview { ++ constructor(renderer, extensions, gl) { ++ this.renderer = renderer; ++ this.DEFAULT_NUMVIEWS = 2; ++ this.maxNumViews = 0; ++ this.gl = gl; ++ this.extensions = extensions; ++ this.available = this.extensions.has('OCULUS_multiview'); ++ if (this.available) { ++ const extension = this.extensions.get('OCULUS_multiview'); ++ this.maxNumViews = this.gl.getParameter(extension.MAX_VIEWS_OVR); ++ this.mat4 = []; ++ this.mat3 = []; ++ this.cameraArray = []; ++ for (var i = 0; i < this.maxNumViews; i++) { ++ this.mat4[i] = new Matrix4(); ++ this.mat3[i] = new Matrix3(); ++ } ++ } ++ } ++ ++ // ++ getCameraArray(camera) { ++ if (camera.isArrayCamera) return camera.cameras; ++ this.cameraArray[0] = camera; ++ return this.cameraArray; ++ } ++ updateCameraProjectionMatricesUniform(camera, uniforms) { ++ var cameras = this.getCameraArray(camera); ++ for (var i = 0; i < cameras.length; i++) { ++ this.mat4[i].copy(cameras[i].projectionMatrix); ++ } ++ uniforms.setValue(this.gl, 'projectionMatrices', this.mat4); ++ } ++ updateCameraViewMatricesUniform(camera, uniforms) { ++ var cameras = this.getCameraArray(camera); ++ for (var i = 0; i < cameras.length; i++) { ++ this.mat4[i].copy(cameras[i].matrixWorldInverse); ++ } ++ uniforms.setValue(this.gl, 'viewMatrices', this.mat4); ++ } ++ updateObjectMatricesUniforms(object, camera, uniforms) { ++ var cameras = this.getCameraArray(camera); ++ for (var i = 0; i < cameras.length; i++) { ++ this.mat4[i].multiplyMatrices(cameras[i].matrixWorldInverse, object.matrixWorld); ++ this.mat3[i].getNormalMatrix(this.mat4[i]); ++ } ++ uniforms.setValue(this.gl, 'modelViewMatrices', this.mat4); ++ uniforms.setValue(this.gl, 'normalMatrices', this.mat3); ++ } ++ } ++ ++ + class Group extends Object3D { + constructor() { + super(); +@@ -18540,6 +18712,26 @@ + dispatchEvent: EventDispatcher.prototype.dispatchEvent + }); + ++ /** ++ * @author fernandojsg / http://fernandojsg.com ++ * @author Takahiro https://github.com/takahirox ++ */ ++ class WebGLMultiviewRenderTarget extends WebGLRenderTarget { ++ constructor(width, height, numViews, options = {}) { ++ super(width, height, options); ++ this.depthBuffer = false; ++ this.stencilBuffer = false; ++ this.numViews = numViews; ++ } ++ copy(source) { ++ super.copy(source); ++ this.numViews = source.numViews; ++ return this; ++ } ++ } ++ WebGLMultiviewRenderTarget.prototype.isWebGLMultiviewRenderTarget = true; ++ ++ + const _moveEvent = { + type: 'move' + }; +@@ -18809,7 +19001,7 @@ + } + + class WebXRManager extends EventDispatcher { +- constructor(renderer, gl) { ++ constructor(renderer, gl, extensions, useMultiview) { + super(); + const scope = this; + let session = null; +@@ -18849,6 +19041,7 @@ + this.layersEnabled = false; + this.enabled = false; + this.isPresenting = false; ++ this.isMultiview = false; + + this.getCameraPose = function () { + return pose; +@@ -19026,24 +19219,35 @@ + depthType = attributes.stencil ? UnsignedInt248Type : UnsignedIntType; + } + ++ scope.isMultiview = useMultiview && extensions.has('OCULUS_multiview'); + const projectionlayerInit = { + colorFormat: gl.RGBA8, + depthFormat: glDepthFormat, + scaleFactor: framebufferScaleFactor + }; ++ if (scope.isMultiview) { ++ projectionlayerInit.textureType = 'texture-array'; ++ } + glBinding = new XRWebGLBinding(session, gl); + glProjLayer = glBinding.createProjectionLayer(projectionlayerInit); + session.updateRenderState({ + layers: [glProjLayer] + }); +- newRenderTarget = new WebGLRenderTarget(glProjLayer.textureWidth, glProjLayer.textureHeight, { ++ const rtOptions = { + format: RGBAFormat, + type: UnsignedByteType, + depthTexture: new DepthTexture(glProjLayer.textureWidth, glProjLayer.textureHeight, depthType, undefined, undefined, undefined, undefined, undefined, undefined, depthFormat), + stencilBuffer: attributes.stencil, + encoding: renderer.outputEncoding, + samples: attributes.antialias ? 4 : 0 +- }); ++ }; ++ if (scope.isMultiview) { ++ const extension = extensions.get('OCULUS_multiview'); ++ this.maxNumViews = gl.getParameter(extension.MAX_VIEWS_OVR); ++ newRenderTarget = new WebGLMultiviewRenderTarget(glProjLayer.textureWidth, glProjLayer.textureHeight, 2, rtOptions); ++ } else { ++ newRenderTarget = new WebGLRenderTarget(glProjLayer.textureWidth, glProjLayer.textureHeight, rtOptions); ++ } + const renderTargetProperties = renderer.properties.get(newRenderTarget); + renderTargetProperties.__ignoreDepthValues = glProjLayer.ignoreDepthValues; + } +@@ -20121,7 +20325,8 @@ + _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true, + _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false, + _powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default', +- _failIfMajorPerformanceCaveat = parameters.failIfMajorPerformanceCaveat !== undefined ? parameters.failIfMajorPerformanceCaveat : false; ++ _failIfMajorPerformanceCaveat = parameters.failIfMajorPerformanceCaveat !== undefined ? parameters.failIfMajorPerformanceCaveat : false, ++ _multiviewStereo = parameters.multiviewStereo !== undefined ? parameters.multiviewStereo : false; + + let _alpha; + +@@ -20292,6 +20497,7 @@ + let extensions, capabilities, state, info; + let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects; + let programCache, materials, renderLists, renderStates, clipping, shadowMap; ++ let multiview; + let background, morphtargets, bufferRenderer, indexedBufferRenderer; + let utils, bindingStates, uniformsGroups; + +@@ -20313,6 +20519,7 @@ + morphtargets = new WebGLMorphtargets(_gl, capabilities, textures); + clipping = new WebGLClipping(properties); + programCache = new WebGLPrograms(_this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping); ++ multiview = new WebGLMultiview(_this, extensions, _gl); + materials = new WebGLMaterials(_this, properties); + renderLists = new WebGLRenderLists(); + renderStates = new WebGLRenderStates(extensions, capabilities); +@@ -20332,7 +20539,7 @@ + } + + initGLContext(); +- const xr = typeof navigator !== 'undefined' && 'xr' in navigator ? new WebXRManager(_this, _gl) : new WebVRManager(_this); ++ const xr = typeof navigator !== 'undefined' && 'xr' in navigator ? new WebXRManager(_this, _gl, extensions, _multiviewStereo) : new WebVRManager(_this); + this.xr = xr; // API + + this.getContext = function () { +@@ -20783,11 +20990,16 @@ + currentRenderState.setupLights(_this.physicallyCorrectLights); + + if (camera.isArrayCamera) { +- const cameras = camera.cameras; ++ if (xr.enabled && xr.isMultiview) { ++ textures.deferTextureUploads = true; ++ renderScene(currentRenderList, scene, camera, camera.cameras[0].viewport); ++ } else { ++ const cameras = camera.cameras; + +- for (let i = 0, l = cameras.length; i < l; i++) { +- const camera2 = cameras[i]; +- renderScene(currentRenderList, scene, camera2, camera2.viewport); ++ for (let i = 0, l = cameras.length; i < l; i++) { ++ const camera2 = cameras[i]; ++ renderScene(currentRenderList, scene, camera2, camera2.viewport); ++ } + } + } else { + renderScene(currentRenderList, scene, camera); +@@ -20807,6 +21019,7 @@ + if (xr.enabled && xr.submitFrame) { + xr.submitFrame(); + } // _gl.finish(); ++ textures.runDeferredUploads(); + + + bindingStates.resetDefaultState(); +@@ -21090,6 +21303,7 @@ + materialProperties.vertexAlphas = parameters.vertexAlphas; + materialProperties.vertexTangents = parameters.vertexTangents; + materialProperties.toneMapping = parameters.toneMapping; ++ materialProperties.numMultiviewViews = parameters.numMultiviewViews; + } + + function setProgram(camera, scene, geometry, material, object) { +@@ -21106,6 +21320,7 @@ + const morphNormals = !!geometry.morphAttributes.normal; + const morphColors = !!geometry.morphAttributes.color; + const toneMapping = material.toneMapped ? _this.toneMapping : NoToneMapping; ++ const numMultiviewViews = _currentRenderTarget && _currentRenderTarget.isWebGLMultiviewRenderTarget ? _currentRenderTarget.numViews : 0; + const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; + const morphTargetsCount = morphAttribute !== undefined ? morphAttribute.length : 0; + const materialProperties = properties.get(material); +@@ -21157,6 +21372,8 @@ + needsProgramChange = true; + } else if (capabilities.isWebGL2 === true && materialProperties.morphTargetsCount !== morphTargetsCount) { + needsProgramChange = true; ++ } else if (materialProperties.numMultiviewViews !== numMultiviewViews) { ++ needsProgramChange = true; + } + } else { + needsProgramChange = true; +@@ -21188,7 +21405,11 @@ + } + + if (refreshProgram || _currentCamera !== camera) { +- p_uniforms.setValue(_gl, 'projectionMatrix', camera.projectionMatrix); ++ if (program.numMultiviewViews > 0) { ++ multiview.updateCameraProjectionMatricesUniform(camera, p_uniforms); ++ } else { ++ p_uniforms.setValue(_gl, 'projectionMatrix', camera.projectionMatrix); ++ } + + if (capabilities.logarithmicDepthBuffer) { + p_uniforms.setValue(_gl, 'logDepthBufFC', 2.0 / (Math.log(camera.far + 1.0) / Math.LN2)); +@@ -21219,7 +21440,11 @@ + } + + if (material.isMeshPhongMaterial || material.isMeshToonMaterial || material.isMeshLambertMaterial || material.isMeshBasicMaterial || material.isMeshStandardMaterial || material.isShaderMaterial || material.isShadowMaterial || object.isSkinnedMesh) { +- p_uniforms.setValue(_gl, 'viewMatrix', camera.matrixWorldInverse); ++ if (program.numMultiviewViews > 0) { ++ multiview.updateCameraViewMatricesUniform(camera, p_uniforms); ++ } else { ++ p_uniforms.setValue(_gl, 'viewMatrix', camera.matrixWorldInverse); ++ } + } + } // skinning and morph target uniforms must be set even if material didn't change + // auto-setting of texture unit for bone and morph texture must go before other textures +@@ -21292,8 +21517,12 @@ + } // common matrices + + +- p_uniforms.setValue(_gl, 'modelViewMatrix', object.modelViewMatrix); +- p_uniforms.setValue(_gl, 'normalMatrix', object.normalMatrix); ++ if (program.numMultiviewViews > 0) { ++ multiview.updateObjectMatricesUniforms(object, camera, p_uniforms); ++ } else { ++ p_uniforms.setValue(_gl, 'modelViewMatrix', object.modelViewMatrix); ++ p_uniforms.setValue(_gl, 'normalMatrix', object.normalMatrix); ++ } + p_uniforms.setValue(_gl, 'modelMatrix', object.matrixWorld); // UBOs + + if (material.isShaderMaterial || material.isRawShaderMaterial) { +@@ -21366,16 +21595,14 @@ + const renderTargetProperties = properties.get(renderTarget); + renderTargetProperties.__hasExternalTextures = true; + +- if (renderTargetProperties.__hasExternalTextures) { +- renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === undefined; ++ renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === undefined; + +- if (!renderTargetProperties.__autoAllocateDepthBuffer) { +- // The multisample_render_to_texture extension doesn't work properly if there +- // are midframe flushes and an external depth buffer. Disable use of the extension. +- if (extensions.has('WEBGL_multisampled_render_to_texture') === true) { +- console.warn('THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided'); +- renderTargetProperties.__useRenderToTexture = false; +- } ++ if (!renderTargetProperties.__autoAllocateDepthBuffer && !_currentRenderTarget.isWebGLMultiviewRenderTarget) { ++ // The multisample_render_to_texture extension doesn't work properly if there ++ // are midframe flushes and an external depth buffer. Disable use of the extension. ++ if (extensions.has('WEBGL_multisampled_render_to_texture') === true) { ++ console.warn('THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided'); ++ renderTargetProperties.__useRenderToTexture = false; + } + } + }; +diff --git a/node_modules/super-three/build/three.min.js b/node_modules/super-three/build/three.min.js +index 0af87af..d22da0c 100644 +--- a/node_modules/super-three/build/three.min.js ++++ b/node_modules/super-three/build/three.min.js +@@ -3,4 +3,4 @@ + * Copyright 2010-2022 Three.js Authors + * SPDX-License-Identifier: MIT + */ +-!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).THREE={})}(this,(function(t){"use strict";const e="147",i=100,n=300,r=301,s=302,a=303,o=304,l=306,c=1e3,h=1001,u=1002,d=1003,p=1004,m=1005,f=1006,g=1007,v=1008,x=1009,_=1012,y=1014,M=1015,b=1016,w=1020,S=1023,T=1026,A=1027,E=33776,C=33777,L=33778,R=33779,P=35840,I=35841,D=35842,N=35843,O=37492,z=37496,U=37808,B=37809,F=37810,k=37811,G=37812,V=37813,H=37814,W=37815,j=37816,q=37817,X=37818,Y=37819,Z=37820,J=37821,K=36492,$=2300,Q=2301,tt=2302,et=2400,it=2401,nt=2402,rt=2500,st=2501,at=3e3,ot=3001,lt="srgb",ct="srgb-linear",ht=7680,ut=35044,dt="300 es",pt=1035;class mt{addEventListener(t,e){void 0===this._listeners&&(this._listeners={});const i=this._listeners;void 0===i[t]&&(i[t]=[]),-1===i[t].indexOf(e)&&i[t].push(e)}hasEventListener(t,e){if(void 0===this._listeners)return!1;const i=this._listeners;return void 0!==i[t]&&-1!==i[t].indexOf(e)}removeEventListener(t,e){if(void 0===this._listeners)return;const i=this._listeners[t];if(void 0!==i){const t=i.indexOf(e);-1!==t&&i.splice(t,1)}}dispatchEvent(t){if(void 0===this._listeners)return;const e=this._listeners[t.type];if(void 0!==e){t.target=this;const i=e.slice(0);for(let e=0,n=i.length;e>8&255]+ft[t>>16&255]+ft[t>>24&255]+"-"+ft[255&e]+ft[e>>8&255]+"-"+ft[e>>16&15|64]+ft[e>>24&255]+"-"+ft[63&i|128]+ft[i>>8&255]+"-"+ft[i>>16&255]+ft[i>>24&255]+ft[255&n]+ft[n>>8&255]+ft[n>>16&255]+ft[n>>24&255]).toLowerCase()}function yt(t,e,i){return Math.max(e,Math.min(i,t))}function Mt(t,e){return(t%e+e)%e}function bt(t,e,i){return(1-i)*t+i*e}function wt(t){return 0==(t&t-1)&&0!==t}function St(t){return Math.pow(2,Math.ceil(Math.log(t)/Math.LN2))}function Tt(t){return Math.pow(2,Math.floor(Math.log(t)/Math.LN2))}function At(t,e){switch(e.constructor){case Float32Array:return t;case Uint16Array:return t/65535;case Uint8Array:return t/255;case Int16Array:return Math.max(t/32767,-1);case Int8Array:return Math.max(t/127,-1);default:throw new Error("Invalid component type.")}}function Et(t,e){switch(e.constructor){case Float32Array:return t;case Uint16Array:return Math.round(65535*t);case Uint8Array:return Math.round(255*t);case Int16Array:return Math.round(32767*t);case Int8Array:return Math.round(127*t);default:throw new Error("Invalid component type.")}}var Ct=Object.freeze({__proto__:null,DEG2RAD:vt,RAD2DEG:xt,generateUUID:_t,clamp:yt,euclideanModulo:Mt,mapLinear:function(t,e,i,n,r){return n+(t-e)*(r-n)/(i-e)},inverseLerp:function(t,e,i){return t!==e?(i-t)/(e-t):0},lerp:bt,damp:function(t,e,i,n){return bt(t,e,1-Math.exp(-i*n))},pingpong:function(t,e=1){return e-Math.abs(Mt(t,2*e)-e)},smoothstep:function(t,e,i){return t<=e?0:t>=i?1:(t=(t-e)/(i-e))*t*(3-2*t)},smootherstep:function(t,e,i){return t<=e?0:t>=i?1:(t=(t-e)/(i-e))*t*t*(t*(6*t-15)+10)},randInt:function(t,e){return t+Math.floor(Math.random()*(e-t+1))},randFloat:function(t,e){return t+Math.random()*(e-t)},randFloatSpread:function(t){return t*(.5-Math.random())},seededRandom:function(t){void 0!==t&&(gt=t);let e=gt+=1831565813;return e=Math.imul(e^e>>>15,1|e),e^=e+Math.imul(e^e>>>7,61|e),((e^e>>>14)>>>0)/4294967296},degToRad:function(t){return t*vt},radToDeg:function(t){return t*xt},isPowerOfTwo:wt,ceilPowerOfTwo:St,floorPowerOfTwo:Tt,setQuaternionFromProperEuler:function(t,e,i,n,r){const s=Math.cos,a=Math.sin,o=s(i/2),l=a(i/2),c=s((e+n)/2),h=a((e+n)/2),u=s((e-n)/2),d=a((e-n)/2),p=s((n-e)/2),m=a((n-e)/2);switch(r){case"XYX":t.set(o*h,l*u,l*d,o*c);break;case"YZY":t.set(l*d,o*h,l*u,o*c);break;case"ZXZ":t.set(l*u,l*d,o*h,o*c);break;case"XZX":t.set(o*h,l*m,l*p,o*c);break;case"YXY":t.set(l*p,o*h,l*m,o*c);break;case"ZYZ":t.set(l*m,l*p,o*h,o*c);break;default:console.warn("THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: "+r)}},normalize:Et,denormalize:At});class Lt{constructor(t=0,e=0){Lt.prototype.isVector2=!0,this.x=t,this.y=e}get width(){return this.x}set width(t){this.x=t}get height(){return this.y}set height(t){this.y=t}set(t,e){return this.x=t,this.y=e,this}setScalar(t){return this.x=t,this.y=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y)}copy(t){return this.x=t.x,this.y=t.y,this}add(t){return this.x+=t.x,this.y+=t.y,this}addScalar(t){return this.x+=t,this.y+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this}subScalar(t){return this.x-=t,this.y-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this}multiply(t){return this.x*=t.x,this.y*=t.y,this}multiplyScalar(t){return this.x*=t,this.y*=t,this}divide(t){return this.x/=t.x,this.y/=t.y,this}divideScalar(t){return this.multiplyScalar(1/t)}applyMatrix3(t){const e=this.x,i=this.y,n=t.elements;return this.x=n[0]*e+n[3]*i+n[6],this.y=n[1]*e+n[4]*i+n[7],this}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this}clamp(t,e){return this.x=Math.max(t.x,Math.min(e.x,this.x)),this.y=Math.max(t.y,Math.min(e.y,this.y)),this}clampScalar(t,e){return this.x=Math.max(t,Math.min(e,this.x)),this.y=Math.max(t,Math.min(e,this.y)),this}clampLength(t,e){const i=this.length();return this.divideScalar(i||1).multiplyScalar(Math.max(t,Math.min(e,i)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this}roundToZero(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this}negate(){return this.x=-this.x,this.y=-this.y,this}dot(t){return this.x*t.x+this.y*t.y}cross(t){return this.x*t.y-this.y*t.x}lengthSq(){return this.x*this.x+this.y*this.y}length(){return Math.sqrt(this.x*this.x+this.y*this.y)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)}normalize(){return this.divideScalar(this.length()||1)}angle(){return Math.atan2(-this.y,-this.x)+Math.PI}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,i=this.y-t.y;return e*e+i*i}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this}lerpVectors(t,e,i){return this.x=t.x+(e.x-t.x)*i,this.y=t.y+(e.y-t.y)*i,this}equals(t){return t.x===this.x&&t.y===this.y}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this}rotateAround(t,e){const i=Math.cos(e),n=Math.sin(e),r=this.x-t.x,s=this.y-t.y;return this.x=r*i-s*n+t.x,this.y=r*n+s*i+t.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}}class Rt{constructor(){Rt.prototype.isMatrix3=!0,this.elements=[1,0,0,0,1,0,0,0,1]}set(t,e,i,n,r,s,a,o,l){const c=this.elements;return c[0]=t,c[1]=n,c[2]=a,c[3]=e,c[4]=r,c[5]=o,c[6]=i,c[7]=s,c[8]=l,this}identity(){return this.set(1,0,0,0,1,0,0,0,1),this}copy(t){const e=this.elements,i=t.elements;return e[0]=i[0],e[1]=i[1],e[2]=i[2],e[3]=i[3],e[4]=i[4],e[5]=i[5],e[6]=i[6],e[7]=i[7],e[8]=i[8],this}extractBasis(t,e,i){return t.setFromMatrix3Column(this,0),e.setFromMatrix3Column(this,1),i.setFromMatrix3Column(this,2),this}setFromMatrix4(t){const e=t.elements;return this.set(e[0],e[4],e[8],e[1],e[5],e[9],e[2],e[6],e[10]),this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const i=t.elements,n=e.elements,r=this.elements,s=i[0],a=i[3],o=i[6],l=i[1],c=i[4],h=i[7],u=i[2],d=i[5],p=i[8],m=n[0],f=n[3],g=n[6],v=n[1],x=n[4],_=n[7],y=n[2],M=n[5],b=n[8];return r[0]=s*m+a*v+o*y,r[3]=s*f+a*x+o*M,r[6]=s*g+a*_+o*b,r[1]=l*m+c*v+h*y,r[4]=l*f+c*x+h*M,r[7]=l*g+c*_+h*b,r[2]=u*m+d*v+p*y,r[5]=u*f+d*x+p*M,r[8]=u*g+d*_+p*b,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[3]*=t,e[6]*=t,e[1]*=t,e[4]*=t,e[7]*=t,e[2]*=t,e[5]*=t,e[8]*=t,this}determinant(){const t=this.elements,e=t[0],i=t[1],n=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8];return e*s*c-e*a*l-i*r*c+i*a*o+n*r*l-n*s*o}invert(){const t=this.elements,e=t[0],i=t[1],n=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8],h=c*s-a*l,u=a*o-c*r,d=l*r-s*o,p=e*h+i*u+n*d;if(0===p)return this.set(0,0,0,0,0,0,0,0,0);const m=1/p;return t[0]=h*m,t[1]=(n*l-c*i)*m,t[2]=(a*i-n*s)*m,t[3]=u*m,t[4]=(c*e-n*o)*m,t[5]=(n*r-a*e)*m,t[6]=d*m,t[7]=(i*o-l*e)*m,t[8]=(s*e-i*r)*m,this}transpose(){let t;const e=this.elements;return t=e[1],e[1]=e[3],e[3]=t,t=e[2],e[2]=e[6],e[6]=t,t=e[5],e[5]=e[7],e[7]=t,this}getNormalMatrix(t){return this.setFromMatrix4(t).invert().transpose()}transposeIntoArray(t){const e=this.elements;return t[0]=e[0],t[1]=e[3],t[2]=e[6],t[3]=e[1],t[4]=e[4],t[5]=e[7],t[6]=e[2],t[7]=e[5],t[8]=e[8],this}setUvTransform(t,e,i,n,r,s,a){const o=Math.cos(r),l=Math.sin(r);return this.set(i*o,i*l,-i*(o*s+l*a)+s+t,-n*l,n*o,-n*(-l*s+o*a)+a+e,0,0,1),this}scale(t,e){return this.premultiply(Pt.makeScale(t,e)),this}rotate(t){return this.premultiply(Pt.makeRotation(-t)),this}translate(t,e){return this.premultiply(Pt.makeTranslation(t,e)),this}makeTranslation(t,e){return this.set(1,0,t,0,1,e,0,0,1),this}makeRotation(t){const e=Math.cos(t),i=Math.sin(t);return this.set(e,-i,0,i,e,0,0,0,1),this}makeScale(t,e){return this.set(t,0,0,0,e,0,0,0,1),this}equals(t){const e=this.elements,i=t.elements;for(let t=0;t<9;t++)if(e[t]!==i[t])return!1;return!0}fromArray(t,e=0){for(let i=0;i<9;i++)this.elements[i]=t[i+e];return this}toArray(t=[],e=0){const i=this.elements;return t[e]=i[0],t[e+1]=i[1],t[e+2]=i[2],t[e+3]=i[3],t[e+4]=i[4],t[e+5]=i[5],t[e+6]=i[6],t[e+7]=i[7],t[e+8]=i[8],t}clone(){return(new this.constructor).fromArray(this.elements)}}const Pt=new Rt;function It(t){for(let e=t.length-1;e>=0;--e)if(t[e]>=65535)return!0;return!1}const Dt={Int8Array:Int8Array,Uint8Array:Uint8Array,Uint8ClampedArray:Uint8ClampedArray,Int16Array:Int16Array,Uint16Array:Uint16Array,Int32Array:Int32Array,Uint32Array:Uint32Array,Float32Array:Float32Array,Float64Array:Float64Array};function Nt(t,e){return new Dt[t](e)}function Ot(t){return document.createElementNS("http://www.w3.org/1999/xhtml",t)}function zt(t){return t<.04045?.0773993808*t:Math.pow(.9478672986*t+.0521327014,2.4)}function Ut(t){return t<.0031308?12.92*t:1.055*Math.pow(t,.41666)-.055}const Bt={[lt]:{[ct]:zt},[ct]:{[lt]:Ut}},Ft={legacyMode:!0,get workingColorSpace(){return ct},set workingColorSpace(t){console.warn("THREE.ColorManagement: .workingColorSpace is readonly.")},convert:function(t,e,i){if(this.legacyMode||e===i||!e||!i)return t;if(Bt[e]&&void 0!==Bt[e][i]){const n=Bt[e][i];return t.r=n(t.r),t.g=n(t.g),t.b=n(t.b),t}throw new Error("Unsupported color space conversion.")},fromWorkingColorSpace:function(t,e){return this.convert(t,this.workingColorSpace,e)},toWorkingColorSpace:function(t,e){return this.convert(t,e,this.workingColorSpace)}},kt={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074},Gt={r:0,g:0,b:0},Vt={h:0,s:0,l:0},Ht={h:0,s:0,l:0};function Wt(t,e,i){return i<0&&(i+=1),i>1&&(i-=1),i<1/6?t+6*(e-t)*i:i<.5?e:i<2/3?t+6*(e-t)*(2/3-i):t}function jt(t,e){return e.r=t.r,e.g=t.g,e.b=t.b,e}class qt{constructor(t,e,i){return this.isColor=!0,this.r=1,this.g=1,this.b=1,void 0===e&&void 0===i?this.set(t):this.setRGB(t,e,i)}set(t){return t&&t.isColor?this.copy(t):"number"==typeof t?this.setHex(t):"string"==typeof t&&this.setStyle(t),this}setScalar(t){return this.r=t,this.g=t,this.b=t,this}setHex(t,e="srgb"){return t=Math.floor(t),this.r=(t>>16&255)/255,this.g=(t>>8&255)/255,this.b=(255&t)/255,Ft.toWorkingColorSpace(this,e),this}setRGB(t,e,i,n=Ft.workingColorSpace){return this.r=t,this.g=e,this.b=i,Ft.toWorkingColorSpace(this,n),this}setHSL(t,e,i,n=Ft.workingColorSpace){if(t=Mt(t,1),e=yt(e,0,1),i=yt(i,0,1),0===e)this.r=this.g=this.b=i;else{const n=i<=.5?i*(1+e):i+e-i*e,r=2*i-n;this.r=Wt(r,n,t+1/3),this.g=Wt(r,n,t),this.b=Wt(r,n,t-1/3)}return Ft.toWorkingColorSpace(this,n),this}setStyle(t,e="srgb"){function i(e){void 0!==e&&parseFloat(e)<1&&console.warn("THREE.Color: Alpha component of "+t+" will be ignored.")}let n;if(n=/^((?:rgb|hsl)a?)\(([^\)]*)\)/.exec(t)){let t;const r=n[1],s=n[2];switch(r){case"rgb":case"rgba":if(t=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(s))return this.r=Math.min(255,parseInt(t[1],10))/255,this.g=Math.min(255,parseInt(t[2],10))/255,this.b=Math.min(255,parseInt(t[3],10))/255,Ft.toWorkingColorSpace(this,e),i(t[4]),this;if(t=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(s))return this.r=Math.min(100,parseInt(t[1],10))/100,this.g=Math.min(100,parseInt(t[2],10))/100,this.b=Math.min(100,parseInt(t[3],10))/100,Ft.toWorkingColorSpace(this,e),i(t[4]),this;break;case"hsl":case"hsla":if(t=/^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(s)){const n=parseFloat(t[1])/360,r=parseFloat(t[2])/100,s=parseFloat(t[3])/100;return i(t[4]),this.setHSL(n,r,s,e)}}}else if(n=/^\#([A-Fa-f\d]+)$/.exec(t)){const t=n[1],i=t.length;if(3===i)return this.r=parseInt(t.charAt(0)+t.charAt(0),16)/255,this.g=parseInt(t.charAt(1)+t.charAt(1),16)/255,this.b=parseInt(t.charAt(2)+t.charAt(2),16)/255,Ft.toWorkingColorSpace(this,e),this;if(6===i)return this.r=parseInt(t.charAt(0)+t.charAt(1),16)/255,this.g=parseInt(t.charAt(2)+t.charAt(3),16)/255,this.b=parseInt(t.charAt(4)+t.charAt(5),16)/255,Ft.toWorkingColorSpace(this,e),this}return t&&t.length>0?this.setColorName(t,e):this}setColorName(t,e="srgb"){const i=kt[t.toLowerCase()];return void 0!==i?this.setHex(i,e):console.warn("THREE.Color: Unknown color "+t),this}clone(){return new this.constructor(this.r,this.g,this.b)}copy(t){return this.r=t.r,this.g=t.g,this.b=t.b,this}copySRGBToLinear(t){return this.r=zt(t.r),this.g=zt(t.g),this.b=zt(t.b),this}copyLinearToSRGB(t){return this.r=Ut(t.r),this.g=Ut(t.g),this.b=Ut(t.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(t="srgb"){return Ft.fromWorkingColorSpace(jt(this,Gt),t),yt(255*Gt.r,0,255)<<16^yt(255*Gt.g,0,255)<<8^yt(255*Gt.b,0,255)<<0}getHexString(t="srgb"){return("000000"+this.getHex(t).toString(16)).slice(-6)}getHSL(t,e=Ft.workingColorSpace){Ft.fromWorkingColorSpace(jt(this,Gt),e);const i=Gt.r,n=Gt.g,r=Gt.b,s=Math.max(i,n,r),a=Math.min(i,n,r);let o,l;const c=(a+s)/2;if(a===s)o=0,l=0;else{const t=s-a;switch(l=c<=.5?t/(s+a):t/(2-s-a),s){case i:o=(n-r)/t+(n2048||e.height>2048?(console.warn("THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons",t),e.toDataURL("image/jpeg",.6)):e.toDataURL("image/png")}static sRGBToLinear(t){if("undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap){const e=Ot("canvas");e.width=t.width,e.height=t.height;const i=e.getContext("2d");i.drawImage(t,0,0,t.width,t.height);const n=i.getImageData(0,0,t.width,t.height),r=n.data;for(let t=0;t1)switch(this.wrapS){case c:t.x=t.x-Math.floor(t.x);break;case h:t.x=t.x<0?0:1;break;case u:1===Math.abs(Math.floor(t.x)%2)?t.x=Math.ceil(t.x)-t.x:t.x=t.x-Math.floor(t.x)}if(t.y<0||t.y>1)switch(this.wrapT){case c:t.y=t.y-Math.floor(t.y);break;case h:t.y=t.y<0?0:1;break;case u:1===Math.abs(Math.floor(t.y)%2)?t.y=Math.ceil(t.y)-t.y:t.y=t.y-Math.floor(t.y)}return this.flipY&&(t.y=1-t.y),t}set needsUpdate(t){!0===t&&(this.version++,this.source.needsUpdate=!0)}}$t.DEFAULT_IMAGE=null,$t.DEFAULT_MAPPING=n,$t.DEFAULT_ANISOTROPY=1;class Qt{constructor(t=0,e=0,i=0,n=1){Qt.prototype.isVector4=!0,this.x=t,this.y=e,this.z=i,this.w=n}get width(){return this.z}set width(t){this.z=t}get height(){return this.w}set height(t){this.w=t}set(t,e,i,n){return this.x=t,this.y=e,this.z=i,this.w=n,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this.w=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setW(t){return this.w=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;case 3:this.w=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;case 3:return this.w;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z,this.w)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this.w=void 0!==t.w?t.w:1,this}add(t){return this.x+=t.x,this.y+=t.y,this.z+=t.z,this.w+=t.w,this}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this.w+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this.w=t.w+e.w,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this.w+=t.w*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this.z-=t.z,this.w-=t.w,this}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this.w-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this.w=t.w-e.w,this}multiply(t){return this.x*=t.x,this.y*=t.y,this.z*=t.z,this.w*=t.w,this}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this.w*=t,this}applyMatrix4(t){const e=this.x,i=this.y,n=this.z,r=this.w,s=t.elements;return this.x=s[0]*e+s[4]*i+s[8]*n+s[12]*r,this.y=s[1]*e+s[5]*i+s[9]*n+s[13]*r,this.z=s[2]*e+s[6]*i+s[10]*n+s[14]*r,this.w=s[3]*e+s[7]*i+s[11]*n+s[15]*r,this}divideScalar(t){return this.multiplyScalar(1/t)}setAxisAngleFromQuaternion(t){this.w=2*Math.acos(t.w);const e=Math.sqrt(1-t.w*t.w);return e<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=t.x/e,this.y=t.y/e,this.z=t.z/e),this}setAxisAngleFromRotationMatrix(t){let e,i,n,r;const s=.01,a=.1,o=t.elements,l=o[0],c=o[4],h=o[8],u=o[1],d=o[5],p=o[9],m=o[2],f=o[6],g=o[10];if(Math.abs(c-u)o&&t>v?tv?o=0?1:-1,n=1-e*e;if(n>Number.EPSILON){const r=Math.sqrt(n),s=Math.atan2(r,e*i);t=Math.sin(t*s)/r,a=Math.sin(a*s)/r}const r=a*i;if(o=o*t+u*r,l=l*t+d*r,c=c*t+p*r,h=h*t+m*r,t===1-a){const t=1/Math.sqrt(o*o+l*l+c*c+h*h);o*=t,l*=t,c*=t,h*=t}}t[e]=o,t[e+1]=l,t[e+2]=c,t[e+3]=h}static multiplyQuaternionsFlat(t,e,i,n,r,s){const a=i[n],o=i[n+1],l=i[n+2],c=i[n+3],h=r[s],u=r[s+1],d=r[s+2],p=r[s+3];return t[e]=a*p+c*h+o*d-l*u,t[e+1]=o*p+c*u+l*h-a*d,t[e+2]=l*p+c*d+a*u-o*h,t[e+3]=c*p-a*h-o*u-l*d,t}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get w(){return this._w}set w(t){this._w=t,this._onChangeCallback()}set(t,e,i,n){return this._x=t,this._y=e,this._z=i,this._w=n,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._w)}copy(t){return this._x=t.x,this._y=t.y,this._z=t.z,this._w=t.w,this._onChangeCallback(),this}setFromEuler(t,e){const i=t._x,n=t._y,r=t._z,s=t._order,a=Math.cos,o=Math.sin,l=a(i/2),c=a(n/2),h=a(r/2),u=o(i/2),d=o(n/2),p=o(r/2);switch(s){case"XYZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"YXZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"ZXY":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"ZYX":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"YZX":this._x=u*c*h+l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h-u*d*p;break;case"XZY":this._x=u*c*h-l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h+u*d*p;break;default:console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: "+s)}return!1!==e&&this._onChangeCallback(),this}setFromAxisAngle(t,e){const i=e/2,n=Math.sin(i);return this._x=t.x*n,this._y=t.y*n,this._z=t.z*n,this._w=Math.cos(i),this._onChangeCallback(),this}setFromRotationMatrix(t){const e=t.elements,i=e[0],n=e[4],r=e[8],s=e[1],a=e[5],o=e[9],l=e[2],c=e[6],h=e[10],u=i+a+h;if(u>0){const t=.5/Math.sqrt(u+1);this._w=.25/t,this._x=(c-o)*t,this._y=(r-l)*t,this._z=(s-n)*t}else if(i>a&&i>h){const t=2*Math.sqrt(1+i-a-h);this._w=(c-o)/t,this._x=.25*t,this._y=(n+s)/t,this._z=(r+l)/t}else if(a>h){const t=2*Math.sqrt(1+a-i-h);this._w=(r-l)/t,this._x=(n+s)/t,this._y=.25*t,this._z=(o+c)/t}else{const t=2*Math.sqrt(1+h-i-a);this._w=(s-n)/t,this._x=(r+l)/t,this._y=(o+c)/t,this._z=.25*t}return this._onChangeCallback(),this}setFromUnitVectors(t,e){let i=t.dot(e)+1;return iMath.abs(t.z)?(this._x=-t.y,this._y=t.x,this._z=0,this._w=i):(this._x=0,this._y=-t.z,this._z=t.y,this._w=i)):(this._x=t.y*e.z-t.z*e.y,this._y=t.z*e.x-t.x*e.z,this._z=t.x*e.y-t.y*e.x,this._w=i),this.normalize()}angleTo(t){return 2*Math.acos(Math.abs(yt(this.dot(t),-1,1)))}rotateTowards(t,e){const i=this.angleTo(t);if(0===i)return this;const n=Math.min(1,e/i);return this.slerp(t,n),this}identity(){return this.set(0,0,0,1)}invert(){return this.conjugate()}conjugate(){return this._x*=-1,this._y*=-1,this._z*=-1,this._onChangeCallback(),this}dot(t){return this._x*t._x+this._y*t._y+this._z*t._z+this._w*t._w}lengthSq(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w}length(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)}normalize(){let t=this.length();return 0===t?(this._x=0,this._y=0,this._z=0,this._w=1):(t=1/t,this._x=this._x*t,this._y=this._y*t,this._z=this._z*t,this._w=this._w*t),this._onChangeCallback(),this}multiply(t){return this.multiplyQuaternions(this,t)}premultiply(t){return this.multiplyQuaternions(t,this)}multiplyQuaternions(t,e){const i=t._x,n=t._y,r=t._z,s=t._w,a=e._x,o=e._y,l=e._z,c=e._w;return this._x=i*c+s*a+n*l-r*o,this._y=n*c+s*o+r*a-i*l,this._z=r*c+s*l+i*o-n*a,this._w=s*c-i*a-n*o-r*l,this._onChangeCallback(),this}slerp(t,e){if(0===e)return this;if(1===e)return this.copy(t);const i=this._x,n=this._y,r=this._z,s=this._w;let a=s*t._w+i*t._x+n*t._y+r*t._z;if(a<0?(this._w=-t._w,this._x=-t._x,this._y=-t._y,this._z=-t._z,a=-a):this.copy(t),a>=1)return this._w=s,this._x=i,this._y=n,this._z=r,this;const o=1-a*a;if(o<=Number.EPSILON){const t=1-e;return this._w=t*s+e*this._w,this._x=t*i+e*this._x,this._y=t*n+e*this._y,this._z=t*r+e*this._z,this.normalize(),this._onChangeCallback(),this}const l=Math.sqrt(o),c=Math.atan2(l,a),h=Math.sin((1-e)*c)/l,u=Math.sin(e*c)/l;return this._w=s*h+this._w*u,this._x=i*h+this._x*u,this._y=n*h+this._y*u,this._z=r*h+this._z*u,this._onChangeCallback(),this}slerpQuaternions(t,e,i){return this.copy(t).slerp(e,i)}random(){const t=Math.random(),e=Math.sqrt(1-t),i=Math.sqrt(t),n=2*Math.PI*Math.random(),r=2*Math.PI*Math.random();return this.set(e*Math.cos(n),i*Math.sin(r),i*Math.cos(r),e*Math.sin(n))}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._w===this._w}fromArray(t,e=0){return this._x=t[e],this._y=t[e+1],this._z=t[e+2],this._w=t[e+3],this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._w,t}fromBufferAttribute(t,e){return this._x=t.getX(e),this._y=t.getY(e),this._z=t.getZ(e),this._w=t.getW(e),this}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._w}}class re{constructor(t=0,e=0,i=0){re.prototype.isVector3=!0,this.x=t,this.y=e,this.z=i}set(t,e,i){return void 0===i&&(i=this.z),this.x=t,this.y=e,this.z=i,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this}add(t){return this.x+=t.x,this.y+=t.y,this.z+=t.z,this}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this.z-=t.z,this}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this}multiply(t){return this.x*=t.x,this.y*=t.y,this.z*=t.z,this}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this}multiplyVectors(t,e){return this.x=t.x*e.x,this.y=t.y*e.y,this.z=t.z*e.z,this}applyEuler(t){return this.applyQuaternion(ae.setFromEuler(t))}applyAxisAngle(t,e){return this.applyQuaternion(ae.setFromAxisAngle(t,e))}applyMatrix3(t){const e=this.x,i=this.y,n=this.z,r=t.elements;return this.x=r[0]*e+r[3]*i+r[6]*n,this.y=r[1]*e+r[4]*i+r[7]*n,this.z=r[2]*e+r[5]*i+r[8]*n,this}applyNormalMatrix(t){return this.applyMatrix3(t).normalize()}applyMatrix4(t){const e=this.x,i=this.y,n=this.z,r=t.elements,s=1/(r[3]*e+r[7]*i+r[11]*n+r[15]);return this.x=(r[0]*e+r[4]*i+r[8]*n+r[12])*s,this.y=(r[1]*e+r[5]*i+r[9]*n+r[13])*s,this.z=(r[2]*e+r[6]*i+r[10]*n+r[14])*s,this}applyQuaternion(t){const e=this.x,i=this.y,n=this.z,r=t.x,s=t.y,a=t.z,o=t.w,l=o*e+s*n-a*i,c=o*i+a*e-r*n,h=o*n+r*i-s*e,u=-r*e-s*i-a*n;return this.x=l*o+u*-r+c*-a-h*-s,this.y=c*o+u*-s+h*-r-l*-a,this.z=h*o+u*-a+l*-s-c*-r,this}project(t){return this.applyMatrix4(t.matrixWorldInverse).applyMatrix4(t.projectionMatrix)}unproject(t){return this.applyMatrix4(t.projectionMatrixInverse).applyMatrix4(t.matrixWorld)}transformDirection(t){const e=this.x,i=this.y,n=this.z,r=t.elements;return this.x=r[0]*e+r[4]*i+r[8]*n,this.y=r[1]*e+r[5]*i+r[9]*n,this.z=r[2]*e+r[6]*i+r[10]*n,this.normalize()}divide(t){return this.x/=t.x,this.y/=t.y,this.z/=t.z,this}divideScalar(t){return this.multiplyScalar(1/t)}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this.z=Math.min(this.z,t.z),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this.z=Math.max(this.z,t.z),this}clamp(t,e){return this.x=Math.max(t.x,Math.min(e.x,this.x)),this.y=Math.max(t.y,Math.min(e.y,this.y)),this.z=Math.max(t.z,Math.min(e.z,this.z)),this}clampScalar(t,e){return this.x=Math.max(t,Math.min(e,this.x)),this.y=Math.max(t,Math.min(e,this.y)),this.z=Math.max(t,Math.min(e,this.z)),this}clampLength(t,e){const i=this.length();return this.divideScalar(i||1).multiplyScalar(Math.max(t,Math.min(e,i)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this}roundToZero(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this.z=this.z<0?Math.ceil(this.z):Math.floor(this.z),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this}dot(t){return this.x*t.x+this.y*t.y+this.z*t.z}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)}normalize(){return this.divideScalar(this.length()||1)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this.z+=(t.z-this.z)*e,this}lerpVectors(t,e,i){return this.x=t.x+(e.x-t.x)*i,this.y=t.y+(e.y-t.y)*i,this.z=t.z+(e.z-t.z)*i,this}cross(t){return this.crossVectors(this,t)}crossVectors(t,e){const i=t.x,n=t.y,r=t.z,s=e.x,a=e.y,o=e.z;return this.x=n*o-r*a,this.y=r*s-i*o,this.z=i*a-n*s,this}projectOnVector(t){const e=t.lengthSq();if(0===e)return this.set(0,0,0);const i=t.dot(this)/e;return this.copy(t).multiplyScalar(i)}projectOnPlane(t){return se.copy(this).projectOnVector(t),this.sub(se)}reflect(t){return this.sub(se.copy(t).multiplyScalar(2*this.dot(t)))}angleTo(t){const e=Math.sqrt(this.lengthSq()*t.lengthSq());if(0===e)return Math.PI/2;const i=this.dot(t)/e;return Math.acos(yt(i,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,i=this.y-t.y,n=this.z-t.z;return e*e+i*i+n*n}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)+Math.abs(this.z-t.z)}setFromSpherical(t){return this.setFromSphericalCoords(t.radius,t.phi,t.theta)}setFromSphericalCoords(t,e,i){const n=Math.sin(e)*t;return this.x=n*Math.sin(i),this.y=Math.cos(e)*t,this.z=n*Math.cos(i),this}setFromCylindrical(t){return this.setFromCylindricalCoords(t.radius,t.theta,t.y)}setFromCylindricalCoords(t,e,i){return this.x=t*Math.sin(e),this.y=i,this.z=t*Math.cos(e),this}setFromMatrixPosition(t){const e=t.elements;return this.x=e[12],this.y=e[13],this.z=e[14],this}setFromMatrixScale(t){const e=this.setFromMatrixColumn(t,0).length(),i=this.setFromMatrixColumn(t,1).length(),n=this.setFromMatrixColumn(t,2).length();return this.x=e,this.y=i,this.z=n,this}setFromMatrixColumn(t,e){return this.fromArray(t.elements,4*e)}setFromMatrix3Column(t,e){return this.fromArray(t.elements,3*e)}setFromEuler(t){return this.x=t._x,this.y=t._y,this.z=t._z,this}equals(t){return t.x===this.x&&t.y===this.y&&t.z===this.z}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this.z=t[e+2],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t[e+2]=this.z,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this.z=t.getZ(e),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}randomDirection(){const t=2*(Math.random()-.5),e=Math.random()*Math.PI*2,i=Math.sqrt(1-t**2);return this.x=i*Math.cos(e),this.y=i*Math.sin(e),this.z=t,this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}}const se=new re,ae=new ne;class oe{constructor(t=new re(1/0,1/0,1/0),e=new re(-1/0,-1/0,-1/0)){this.isBox3=!0,this.min=t,this.max=e}set(t,e){return this.min.copy(t),this.max.copy(e),this}setFromArray(t){let e=1/0,i=1/0,n=1/0,r=-1/0,s=-1/0,a=-1/0;for(let o=0,l=t.length;or&&(r=l),c>s&&(s=c),h>a&&(a=h)}return this.min.set(e,i,n),this.max.set(r,s,a),this}setFromBufferAttribute(t){let e=1/0,i=1/0,n=1/0,r=-1/0,s=-1/0,a=-1/0;for(let o=0,l=t.count;or&&(r=l),c>s&&(s=c),h>a&&(a=h)}return this.min.set(e,i,n),this.max.set(r,s,a),this}setFromPoints(t){this.makeEmpty();for(let e=0,i=t.length;ethis.max.x||t.ythis.max.y||t.zthis.max.z)}containsBox(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y&&this.min.z<=t.min.z&&t.max.z<=this.max.z}getParameter(t,e){return e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y),(t.z-this.min.z)/(this.max.z-this.min.z))}intersectsBox(t){return!(t.max.xthis.max.x||t.max.ythis.max.y||t.max.zthis.max.z)}intersectsSphere(t){return this.clampPoint(t.center,ce),ce.distanceToSquared(t.center)<=t.radius*t.radius}intersectsPlane(t){let e,i;return t.normal.x>0?(e=t.normal.x*this.min.x,i=t.normal.x*this.max.x):(e=t.normal.x*this.max.x,i=t.normal.x*this.min.x),t.normal.y>0?(e+=t.normal.y*this.min.y,i+=t.normal.y*this.max.y):(e+=t.normal.y*this.max.y,i+=t.normal.y*this.min.y),t.normal.z>0?(e+=t.normal.z*this.min.z,i+=t.normal.z*this.max.z):(e+=t.normal.z*this.max.z,i+=t.normal.z*this.min.z),e<=-t.constant&&i>=-t.constant}intersectsTriangle(t){if(this.isEmpty())return!1;this.getCenter(ve),xe.subVectors(this.max,ve),ue.subVectors(t.a,ve),de.subVectors(t.b,ve),pe.subVectors(t.c,ve),me.subVectors(de,ue),fe.subVectors(pe,de),ge.subVectors(ue,pe);let e=[0,-me.z,me.y,0,-fe.z,fe.y,0,-ge.z,ge.y,me.z,0,-me.x,fe.z,0,-fe.x,ge.z,0,-ge.x,-me.y,me.x,0,-fe.y,fe.x,0,-ge.y,ge.x,0];return!!Me(e,ue,de,pe,xe)&&(e=[1,0,0,0,1,0,0,0,1],!!Me(e,ue,de,pe,xe)&&(_e.crossVectors(me,fe),e=[_e.x,_e.y,_e.z],Me(e,ue,de,pe,xe)))}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return ce.copy(t).clamp(this.min,this.max).sub(t).length()}getBoundingSphere(t){return this.getCenter(t.center),t.radius=.5*this.getSize(ce).length(),t}intersect(t){return this.min.max(t.min),this.max.min(t.max),this.isEmpty()&&this.makeEmpty(),this}union(t){return this.min.min(t.min),this.max.max(t.max),this}applyMatrix4(t){return this.isEmpty()||(le[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(t),le[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(t),le[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(t),le[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(t),le[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(t),le[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(t),le[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(t),le[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(t),this.setFromPoints(le)),this}translate(t){return this.min.add(t),this.max.add(t),this}equals(t){return t.min.equals(this.min)&&t.max.equals(this.max)}}const le=[new re,new re,new re,new re,new re,new re,new re,new re],ce=new re,he=new oe,ue=new re,de=new re,pe=new re,me=new re,fe=new re,ge=new re,ve=new re,xe=new re,_e=new re,ye=new re;function Me(t,e,i,n,r){for(let s=0,a=t.length-3;s<=a;s+=3){ye.fromArray(t,s);const a=r.x*Math.abs(ye.x)+r.y*Math.abs(ye.y)+r.z*Math.abs(ye.z),o=e.dot(ye),l=i.dot(ye),c=n.dot(ye);if(Math.max(-Math.max(o,l,c),Math.min(o,l,c))>a)return!1}return!0}const be=new oe,we=new re,Se=new re;class Te{constructor(t=new re,e=-1){this.center=t,this.radius=e}set(t,e){return this.center.copy(t),this.radius=e,this}setFromPoints(t,e){const i=this.center;void 0!==e?i.copy(e):be.setFromPoints(t).getCenter(i);let n=0;for(let e=0,r=t.length;ethis.radius*this.radius&&(e.sub(this.center).normalize(),e.multiplyScalar(this.radius).add(this.center)),e}getBoundingBox(t){return this.isEmpty()?(t.makeEmpty(),t):(t.set(this.center,this.center),t.expandByScalar(this.radius),t)}applyMatrix4(t){return this.center.applyMatrix4(t),this.radius=this.radius*t.getMaxScaleOnAxis(),this}translate(t){return this.center.add(t),this}expandByPoint(t){if(this.isEmpty())return this.center.copy(t),this.radius=0,this;we.subVectors(t,this.center);const e=we.lengthSq();if(e>this.radius*this.radius){const t=Math.sqrt(e),i=.5*(t-this.radius);this.center.addScaledVector(we,i/t),this.radius+=i}return this}union(t){return t.isEmpty()?this:this.isEmpty()?(this.copy(t),this):(!0===this.center.equals(t.center)?this.radius=Math.max(this.radius,t.radius):(Se.subVectors(t.center,this.center).setLength(t.radius),this.expandByPoint(we.copy(t.center).add(Se)),this.expandByPoint(we.copy(t.center).sub(Se))),this)}equals(t){return t.center.equals(this.center)&&t.radius===this.radius}clone(){return(new this.constructor).copy(this)}}const Ae=new re,Ee=new re,Ce=new re,Le=new re,Re=new re,Pe=new re,Ie=new re;class De{constructor(t=new re,e=new re(0,0,-1)){this.origin=t,this.direction=e}set(t,e){return this.origin.copy(t),this.direction.copy(e),this}copy(t){return this.origin.copy(t.origin),this.direction.copy(t.direction),this}at(t,e){return e.copy(this.direction).multiplyScalar(t).add(this.origin)}lookAt(t){return this.direction.copy(t).sub(this.origin).normalize(),this}recast(t){return this.origin.copy(this.at(t,Ae)),this}closestPointToPoint(t,e){e.subVectors(t,this.origin);const i=e.dot(this.direction);return i<0?e.copy(this.origin):e.copy(this.direction).multiplyScalar(i).add(this.origin)}distanceToPoint(t){return Math.sqrt(this.distanceSqToPoint(t))}distanceSqToPoint(t){const e=Ae.subVectors(t,this.origin).dot(this.direction);return e<0?this.origin.distanceToSquared(t):(Ae.copy(this.direction).multiplyScalar(e).add(this.origin),Ae.distanceToSquared(t))}distanceSqToSegment(t,e,i,n){Ee.copy(t).add(e).multiplyScalar(.5),Ce.copy(e).sub(t).normalize(),Le.copy(this.origin).sub(Ee);const r=.5*t.distanceTo(e),s=-this.direction.dot(Ce),a=Le.dot(this.direction),o=-Le.dot(Ce),l=Le.lengthSq(),c=Math.abs(1-s*s);let h,u,d,p;if(c>0)if(h=s*o-a,u=s*a-o,p=r*c,h>=0)if(u>=-p)if(u<=p){const t=1/c;h*=t,u*=t,d=h*(h+s*u+2*a)+u*(s*h+u+2*o)+l}else u=r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;else u=-r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;else u<=-p?(h=Math.max(0,-(-s*r+a)),u=h>0?-r:Math.min(Math.max(-r,-o),r),d=-h*h+u*(u+2*o)+l):u<=p?(h=0,u=Math.min(Math.max(-r,-o),r),d=u*(u+2*o)+l):(h=Math.max(0,-(s*r+a)),u=h>0?r:Math.min(Math.max(-r,-o),r),d=-h*h+u*(u+2*o)+l);else u=s>0?-r:r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;return i&&i.copy(this.direction).multiplyScalar(h).add(this.origin),n&&n.copy(Ce).multiplyScalar(u).add(Ee),d}intersectSphere(t,e){Ae.subVectors(t.center,this.origin);const i=Ae.dot(this.direction),n=Ae.dot(Ae)-i*i,r=t.radius*t.radius;if(n>r)return null;const s=Math.sqrt(r-n),a=i-s,o=i+s;return a<0&&o<0?null:a<0?this.at(o,e):this.at(a,e)}intersectsSphere(t){return this.distanceSqToPoint(t.center)<=t.radius*t.radius}distanceToPlane(t){const e=t.normal.dot(this.direction);if(0===e)return 0===t.distanceToPoint(this.origin)?0:null;const i=-(this.origin.dot(t.normal)+t.constant)/e;return i>=0?i:null}intersectPlane(t,e){const i=this.distanceToPlane(t);return null===i?null:this.at(i,e)}intersectsPlane(t){const e=t.distanceToPoint(this.origin);if(0===e)return!0;return t.normal.dot(this.direction)*e<0}intersectBox(t,e){let i,n,r,s,a,o;const l=1/this.direction.x,c=1/this.direction.y,h=1/this.direction.z,u=this.origin;return l>=0?(i=(t.min.x-u.x)*l,n=(t.max.x-u.x)*l):(i=(t.max.x-u.x)*l,n=(t.min.x-u.x)*l),c>=0?(r=(t.min.y-u.y)*c,s=(t.max.y-u.y)*c):(r=(t.max.y-u.y)*c,s=(t.min.y-u.y)*c),i>s||r>n?null:((r>i||isNaN(i))&&(i=r),(s=0?(a=(t.min.z-u.z)*h,o=(t.max.z-u.z)*h):(a=(t.max.z-u.z)*h,o=(t.min.z-u.z)*h),i>o||a>n?null:((a>i||i!=i)&&(i=a),(o=0?i:n,e)))}intersectsBox(t){return null!==this.intersectBox(t,Ae)}intersectTriangle(t,e,i,n,r){Re.subVectors(e,t),Pe.subVectors(i,t),Ie.crossVectors(Re,Pe);let s,a=this.direction.dot(Ie);if(a>0){if(n)return null;s=1}else{if(!(a<0))return null;s=-1,a=-a}Le.subVectors(this.origin,t);const o=s*this.direction.dot(Pe.crossVectors(Le,Pe));if(o<0)return null;const l=s*this.direction.dot(Re.cross(Le));if(l<0)return null;if(o+l>a)return null;const c=-s*Le.dot(Ie);return c<0?null:this.at(c/a,r)}applyMatrix4(t){return this.origin.applyMatrix4(t),this.direction.transformDirection(t),this}equals(t){return t.origin.equals(this.origin)&&t.direction.equals(this.direction)}clone(){return(new this.constructor).copy(this)}}class Ne{constructor(){Ne.prototype.isMatrix4=!0,this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}set(t,e,i,n,r,s,a,o,l,c,h,u,d,p,m,f){const g=this.elements;return g[0]=t,g[4]=e,g[8]=i,g[12]=n,g[1]=r,g[5]=s,g[9]=a,g[13]=o,g[2]=l,g[6]=c,g[10]=h,g[14]=u,g[3]=d,g[7]=p,g[11]=m,g[15]=f,this}identity(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this}clone(){return(new Ne).fromArray(this.elements)}copy(t){const e=this.elements,i=t.elements;return e[0]=i[0],e[1]=i[1],e[2]=i[2],e[3]=i[3],e[4]=i[4],e[5]=i[5],e[6]=i[6],e[7]=i[7],e[8]=i[8],e[9]=i[9],e[10]=i[10],e[11]=i[11],e[12]=i[12],e[13]=i[13],e[14]=i[14],e[15]=i[15],this}copyPosition(t){const e=this.elements,i=t.elements;return e[12]=i[12],e[13]=i[13],e[14]=i[14],this}setFromMatrix3(t){const e=t.elements;return this.set(e[0],e[3],e[6],0,e[1],e[4],e[7],0,e[2],e[5],e[8],0,0,0,0,1),this}extractBasis(t,e,i){return t.setFromMatrixColumn(this,0),e.setFromMatrixColumn(this,1),i.setFromMatrixColumn(this,2),this}makeBasis(t,e,i){return this.set(t.x,e.x,i.x,0,t.y,e.y,i.y,0,t.z,e.z,i.z,0,0,0,0,1),this}extractRotation(t){const e=this.elements,i=t.elements,n=1/Oe.setFromMatrixColumn(t,0).length(),r=1/Oe.setFromMatrixColumn(t,1).length(),s=1/Oe.setFromMatrixColumn(t,2).length();return e[0]=i[0]*n,e[1]=i[1]*n,e[2]=i[2]*n,e[3]=0,e[4]=i[4]*r,e[5]=i[5]*r,e[6]=i[6]*r,e[7]=0,e[8]=i[8]*s,e[9]=i[9]*s,e[10]=i[10]*s,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromEuler(t){const e=this.elements,i=t.x,n=t.y,r=t.z,s=Math.cos(i),a=Math.sin(i),o=Math.cos(n),l=Math.sin(n),c=Math.cos(r),h=Math.sin(r);if("XYZ"===t.order){const t=s*c,i=s*h,n=a*c,r=a*h;e[0]=o*c,e[4]=-o*h,e[8]=l,e[1]=i+n*l,e[5]=t-r*l,e[9]=-a*o,e[2]=r-t*l,e[6]=n+i*l,e[10]=s*o}else if("YXZ"===t.order){const t=o*c,i=o*h,n=l*c,r=l*h;e[0]=t+r*a,e[4]=n*a-i,e[8]=s*l,e[1]=s*h,e[5]=s*c,e[9]=-a,e[2]=i*a-n,e[6]=r+t*a,e[10]=s*o}else if("ZXY"===t.order){const t=o*c,i=o*h,n=l*c,r=l*h;e[0]=t-r*a,e[4]=-s*h,e[8]=n+i*a,e[1]=i+n*a,e[5]=s*c,e[9]=r-t*a,e[2]=-s*l,e[6]=a,e[10]=s*o}else if("ZYX"===t.order){const t=s*c,i=s*h,n=a*c,r=a*h;e[0]=o*c,e[4]=n*l-i,e[8]=t*l+r,e[1]=o*h,e[5]=r*l+t,e[9]=i*l-n,e[2]=-l,e[6]=a*o,e[10]=s*o}else if("YZX"===t.order){const t=s*o,i=s*l,n=a*o,r=a*l;e[0]=o*c,e[4]=r-t*h,e[8]=n*h+i,e[1]=h,e[5]=s*c,e[9]=-a*c,e[2]=-l*c,e[6]=i*h+n,e[10]=t-r*h}else if("XZY"===t.order){const t=s*o,i=s*l,n=a*o,r=a*l;e[0]=o*c,e[4]=-h,e[8]=l*c,e[1]=t*h+r,e[5]=s*c,e[9]=i*h-n,e[2]=n*h-i,e[6]=a*c,e[10]=r*h+t}return e[3]=0,e[7]=0,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromQuaternion(t){return this.compose(Ue,t,Be)}lookAt(t,e,i){const n=this.elements;return Ge.subVectors(t,e),0===Ge.lengthSq()&&(Ge.z=1),Ge.normalize(),Fe.crossVectors(i,Ge),0===Fe.lengthSq()&&(1===Math.abs(i.z)?Ge.x+=1e-4:Ge.z+=1e-4,Ge.normalize(),Fe.crossVectors(i,Ge)),Fe.normalize(),ke.crossVectors(Ge,Fe),n[0]=Fe.x,n[4]=ke.x,n[8]=Ge.x,n[1]=Fe.y,n[5]=ke.y,n[9]=Ge.y,n[2]=Fe.z,n[6]=ke.z,n[10]=Ge.z,this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const i=t.elements,n=e.elements,r=this.elements,s=i[0],a=i[4],o=i[8],l=i[12],c=i[1],h=i[5],u=i[9],d=i[13],p=i[2],m=i[6],f=i[10],g=i[14],v=i[3],x=i[7],_=i[11],y=i[15],M=n[0],b=n[4],w=n[8],S=n[12],T=n[1],A=n[5],E=n[9],C=n[13],L=n[2],R=n[6],P=n[10],I=n[14],D=n[3],N=n[7],O=n[11],z=n[15];return r[0]=s*M+a*T+o*L+l*D,r[4]=s*b+a*A+o*R+l*N,r[8]=s*w+a*E+o*P+l*O,r[12]=s*S+a*C+o*I+l*z,r[1]=c*M+h*T+u*L+d*D,r[5]=c*b+h*A+u*R+d*N,r[9]=c*w+h*E+u*P+d*O,r[13]=c*S+h*C+u*I+d*z,r[2]=p*M+m*T+f*L+g*D,r[6]=p*b+m*A+f*R+g*N,r[10]=p*w+m*E+f*P+g*O,r[14]=p*S+m*C+f*I+g*z,r[3]=v*M+x*T+_*L+y*D,r[7]=v*b+x*A+_*R+y*N,r[11]=v*w+x*E+_*P+y*O,r[15]=v*S+x*C+_*I+y*z,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[4]*=t,e[8]*=t,e[12]*=t,e[1]*=t,e[5]*=t,e[9]*=t,e[13]*=t,e[2]*=t,e[6]*=t,e[10]*=t,e[14]*=t,e[3]*=t,e[7]*=t,e[11]*=t,e[15]*=t,this}determinant(){const t=this.elements,e=t[0],i=t[4],n=t[8],r=t[12],s=t[1],a=t[5],o=t[9],l=t[13],c=t[2],h=t[6],u=t[10],d=t[14];return t[3]*(+r*o*h-n*l*h-r*a*u+i*l*u+n*a*d-i*o*d)+t[7]*(+e*o*d-e*l*u+r*s*u-n*s*d+n*l*c-r*o*c)+t[11]*(+e*l*h-e*a*d-r*s*h+i*s*d+r*a*c-i*l*c)+t[15]*(-n*a*c-e*o*h+e*a*u+n*s*h-i*s*u+i*o*c)}transpose(){const t=this.elements;let e;return e=t[1],t[1]=t[4],t[4]=e,e=t[2],t[2]=t[8],t[8]=e,e=t[6],t[6]=t[9],t[9]=e,e=t[3],t[3]=t[12],t[12]=e,e=t[7],t[7]=t[13],t[13]=e,e=t[11],t[11]=t[14],t[14]=e,this}setPosition(t,e,i){const n=this.elements;return t.isVector3?(n[12]=t.x,n[13]=t.y,n[14]=t.z):(n[12]=t,n[13]=e,n[14]=i),this}invert(){const t=this.elements,e=t[0],i=t[1],n=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8],h=t[9],u=t[10],d=t[11],p=t[12],m=t[13],f=t[14],g=t[15],v=h*f*l-m*u*l+m*o*d-a*f*d-h*o*g+a*u*g,x=p*u*l-c*f*l-p*o*d+s*f*d+c*o*g-s*u*g,_=c*m*l-p*h*l+p*a*d-s*m*d-c*a*g+s*h*g,y=p*h*o-c*m*o-p*a*u+s*m*u+c*a*f-s*h*f,M=e*v+i*x+n*_+r*y;if(0===M)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);const b=1/M;return t[0]=v*b,t[1]=(m*u*r-h*f*r-m*n*d+i*f*d+h*n*g-i*u*g)*b,t[2]=(a*f*r-m*o*r+m*n*l-i*f*l-a*n*g+i*o*g)*b,t[3]=(h*o*r-a*u*r-h*n*l+i*u*l+a*n*d-i*o*d)*b,t[4]=x*b,t[5]=(c*f*r-p*u*r+p*n*d-e*f*d-c*n*g+e*u*g)*b,t[6]=(p*o*r-s*f*r-p*n*l+e*f*l+s*n*g-e*o*g)*b,t[7]=(s*u*r-c*o*r+c*n*l-e*u*l-s*n*d+e*o*d)*b,t[8]=_*b,t[9]=(p*h*r-c*m*r-p*i*d+e*m*d+c*i*g-e*h*g)*b,t[10]=(s*m*r-p*a*r+p*i*l-e*m*l-s*i*g+e*a*g)*b,t[11]=(c*a*r-s*h*r-c*i*l+e*h*l+s*i*d-e*a*d)*b,t[12]=y*b,t[13]=(c*m*n-p*h*n+p*i*u-e*m*u-c*i*f+e*h*f)*b,t[14]=(p*a*n-s*m*n-p*i*o+e*m*o+s*i*f-e*a*f)*b,t[15]=(s*h*n-c*a*n+c*i*o-e*h*o-s*i*u+e*a*u)*b,this}scale(t){const e=this.elements,i=t.x,n=t.y,r=t.z;return e[0]*=i,e[4]*=n,e[8]*=r,e[1]*=i,e[5]*=n,e[9]*=r,e[2]*=i,e[6]*=n,e[10]*=r,e[3]*=i,e[7]*=n,e[11]*=r,this}getMaxScaleOnAxis(){const t=this.elements,e=t[0]*t[0]+t[1]*t[1]+t[2]*t[2],i=t[4]*t[4]+t[5]*t[5]+t[6]*t[6],n=t[8]*t[8]+t[9]*t[9]+t[10]*t[10];return Math.sqrt(Math.max(e,i,n))}makeTranslation(t,e,i){return this.set(1,0,0,t,0,1,0,e,0,0,1,i,0,0,0,1),this}makeRotationX(t){const e=Math.cos(t),i=Math.sin(t);return this.set(1,0,0,0,0,e,-i,0,0,i,e,0,0,0,0,1),this}makeRotationY(t){const e=Math.cos(t),i=Math.sin(t);return this.set(e,0,i,0,0,1,0,0,-i,0,e,0,0,0,0,1),this}makeRotationZ(t){const e=Math.cos(t),i=Math.sin(t);return this.set(e,-i,0,0,i,e,0,0,0,0,1,0,0,0,0,1),this}makeRotationAxis(t,e){const i=Math.cos(e),n=Math.sin(e),r=1-i,s=t.x,a=t.y,o=t.z,l=r*s,c=r*a;return this.set(l*s+i,l*a-n*o,l*o+n*a,0,l*a+n*o,c*a+i,c*o-n*s,0,l*o-n*a,c*o+n*s,r*o*o+i,0,0,0,0,1),this}makeScale(t,e,i){return this.set(t,0,0,0,0,e,0,0,0,0,i,0,0,0,0,1),this}makeShear(t,e,i,n,r,s){return this.set(1,i,r,0,t,1,s,0,e,n,1,0,0,0,0,1),this}compose(t,e,i){const n=this.elements,r=e._x,s=e._y,a=e._z,o=e._w,l=r+r,c=s+s,h=a+a,u=r*l,d=r*c,p=r*h,m=s*c,f=s*h,g=a*h,v=o*l,x=o*c,_=o*h,y=i.x,M=i.y,b=i.z;return n[0]=(1-(m+g))*y,n[1]=(d+_)*y,n[2]=(p-x)*y,n[3]=0,n[4]=(d-_)*M,n[5]=(1-(u+g))*M,n[6]=(f+v)*M,n[7]=0,n[8]=(p+x)*b,n[9]=(f-v)*b,n[10]=(1-(u+m))*b,n[11]=0,n[12]=t.x,n[13]=t.y,n[14]=t.z,n[15]=1,this}decompose(t,e,i){const n=this.elements;let r=Oe.set(n[0],n[1],n[2]).length();const s=Oe.set(n[4],n[5],n[6]).length(),a=Oe.set(n[8],n[9],n[10]).length();this.determinant()<0&&(r=-r),t.x=n[12],t.y=n[13],t.z=n[14],ze.copy(this);const o=1/r,l=1/s,c=1/a;return ze.elements[0]*=o,ze.elements[1]*=o,ze.elements[2]*=o,ze.elements[4]*=l,ze.elements[5]*=l,ze.elements[6]*=l,ze.elements[8]*=c,ze.elements[9]*=c,ze.elements[10]*=c,e.setFromRotationMatrix(ze),i.x=r,i.y=s,i.z=a,this}makePerspective(t,e,i,n,r,s){const a=this.elements,o=2*r/(e-t),l=2*r/(i-n),c=(e+t)/(e-t),h=(i+n)/(i-n),u=-(s+r)/(s-r),d=-2*s*r/(s-r);return a[0]=o,a[4]=0,a[8]=c,a[12]=0,a[1]=0,a[5]=l,a[9]=h,a[13]=0,a[2]=0,a[6]=0,a[10]=u,a[14]=d,a[3]=0,a[7]=0,a[11]=-1,a[15]=0,this}makeOrthographic(t,e,i,n,r,s){const a=this.elements,o=1/(e-t),l=1/(i-n),c=1/(s-r),h=(e+t)*o,u=(i+n)*l,d=(s+r)*c;return a[0]=2*o,a[4]=0,a[8]=0,a[12]=-h,a[1]=0,a[5]=2*l,a[9]=0,a[13]=-u,a[2]=0,a[6]=0,a[10]=-2*c,a[14]=-d,a[3]=0,a[7]=0,a[11]=0,a[15]=1,this}equals(t){const e=this.elements,i=t.elements;for(let t=0;t<16;t++)if(e[t]!==i[t])return!1;return!0}fromArray(t,e=0){for(let i=0;i<16;i++)this.elements[i]=t[i+e];return this}toArray(t=[],e=0){const i=this.elements;return t[e]=i[0],t[e+1]=i[1],t[e+2]=i[2],t[e+3]=i[3],t[e+4]=i[4],t[e+5]=i[5],t[e+6]=i[6],t[e+7]=i[7],t[e+8]=i[8],t[e+9]=i[9],t[e+10]=i[10],t[e+11]=i[11],t[e+12]=i[12],t[e+13]=i[13],t[e+14]=i[14],t[e+15]=i[15],t}}const Oe=new re,ze=new Ne,Ue=new re(0,0,0),Be=new re(1,1,1),Fe=new re,ke=new re,Ge=new re,Ve=new Ne,He=new ne;class We{constructor(t=0,e=0,i=0,n=We.DefaultOrder){this.isEuler=!0,this._x=t,this._y=e,this._z=i,this._order=n}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get order(){return this._order}set order(t){this._order=t,this._onChangeCallback()}set(t,e,i,n=this._order){return this._x=t,this._y=e,this._z=i,this._order=n,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._order)}copy(t){return this._x=t._x,this._y=t._y,this._z=t._z,this._order=t._order,this._onChangeCallback(),this}setFromRotationMatrix(t,e=this._order,i=!0){const n=t.elements,r=n[0],s=n[4],a=n[8],o=n[1],l=n[5],c=n[9],h=n[2],u=n[6],d=n[10];switch(e){case"XYZ":this._y=Math.asin(yt(a,-1,1)),Math.abs(a)<.9999999?(this._x=Math.atan2(-c,d),this._z=Math.atan2(-s,r)):(this._x=Math.atan2(u,l),this._z=0);break;case"YXZ":this._x=Math.asin(-yt(c,-1,1)),Math.abs(c)<.9999999?(this._y=Math.atan2(a,d),this._z=Math.atan2(o,l)):(this._y=Math.atan2(-h,r),this._z=0);break;case"ZXY":this._x=Math.asin(yt(u,-1,1)),Math.abs(u)<.9999999?(this._y=Math.atan2(-h,d),this._z=Math.atan2(-s,l)):(this._y=0,this._z=Math.atan2(o,r));break;case"ZYX":this._y=Math.asin(-yt(h,-1,1)),Math.abs(h)<.9999999?(this._x=Math.atan2(u,d),this._z=Math.atan2(o,r)):(this._x=0,this._z=Math.atan2(-s,l));break;case"YZX":this._z=Math.asin(yt(o,-1,1)),Math.abs(o)<.9999999?(this._x=Math.atan2(-c,l),this._y=Math.atan2(-h,r)):(this._x=0,this._y=Math.atan2(a,d));break;case"XZY":this._z=Math.asin(-yt(s,-1,1)),Math.abs(s)<.9999999?(this._x=Math.atan2(u,l),this._y=Math.atan2(a,r)):(this._x=Math.atan2(-c,d),this._y=0);break;default:console.warn("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: "+e)}return this._order=e,!0===i&&this._onChangeCallback(),this}setFromQuaternion(t,e,i){return Ve.makeRotationFromQuaternion(t),this.setFromRotationMatrix(Ve,e,i)}setFromVector3(t,e=this._order){return this.set(t.x,t.y,t.z,e)}reorder(t){return He.setFromEuler(this),this.setFromQuaternion(He,t)}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._order===this._order}fromArray(t){return this._x=t[0],this._y=t[1],this._z=t[2],void 0!==t[3]&&(this._order=t[3]),this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._order,t}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._order}toVector3(){console.error("THREE.Euler: .toVector3() has been removed. Use Vector3.setFromEuler() instead")}}We.DefaultOrder="XYZ",We.RotationOrders=["XYZ","YZX","ZXY","XZY","YXZ","ZYX"];class je{constructor(){this.mask=1}set(t){this.mask=(1<>>0}enable(t){this.mask|=1<1){for(let t=0;t1){for(let t=0;t0){n.children=[];for(let e=0;e0){n.animations=[];for(let e=0;e0&&(i.geometries=e),n.length>0&&(i.materials=n),r.length>0&&(i.textures=r),a.length>0&&(i.images=a),o.length>0&&(i.shapes=o),l.length>0&&(i.skeletons=l),c.length>0&&(i.animations=c),h.length>0&&(i.nodes=h)}return i.object=n,i;function s(t){const e=[];for(const i in t){const n=t[i];delete n.metadata,e.push(n)}return e}}clone(t){return(new this.constructor).copy(this,t)}copy(t,e=!0){if(this.name=t.name,this.up.copy(t.up),this.position.copy(t.position),this.rotation.order=t.rotation.order,this.quaternion.copy(t.quaternion),this.scale.copy(t.scale),this.matrix.copy(t.matrix),this.matrixWorld.copy(t.matrixWorld),this.matrixAutoUpdate=t.matrixAutoUpdate,this.matrixWorldNeedsUpdate=t.matrixWorldNeedsUpdate,this.matrixWorldAutoUpdate=t.matrixWorldAutoUpdate,this.layers.mask=t.layers.mask,this.visible=t.visible,this.castShadow=t.castShadow,this.receiveShadow=t.receiveShadow,this.frustumCulled=t.frustumCulled,this.renderOrder=t.renderOrder,this.userData=JSON.parse(JSON.stringify(t.userData)),!0===e)for(let e=0;e0?n.multiplyScalar(1/Math.sqrt(r)):n.set(0,0,0)}static getBarycoord(t,e,i,n,r){ai.subVectors(n,e),oi.subVectors(i,e),li.subVectors(t,e);const s=ai.dot(ai),a=ai.dot(oi),o=ai.dot(li),l=oi.dot(oi),c=oi.dot(li),h=s*l-a*a;if(0===h)return r.set(-2,-1,-1);const u=1/h,d=(l*o-a*c)*u,p=(s*c-a*o)*u;return r.set(1-d-p,p,d)}static containsPoint(t,e,i,n){return this.getBarycoord(t,e,i,n,ci),ci.x>=0&&ci.y>=0&&ci.x+ci.y<=1}static getUV(t,e,i,n,r,s,a,o){return this.getBarycoord(t,e,i,n,ci),o.set(0,0),o.addScaledVector(r,ci.x),o.addScaledVector(s,ci.y),o.addScaledVector(a,ci.z),o}static isFrontFacing(t,e,i,n){return ai.subVectors(i,e),oi.subVectors(t,e),ai.cross(oi).dot(n)<0}set(t,e,i){return this.a.copy(t),this.b.copy(e),this.c.copy(i),this}setFromPointsAndIndices(t,e,i,n){return this.a.copy(t[e]),this.b.copy(t[i]),this.c.copy(t[n]),this}setFromAttributeAndIndices(t,e,i,n){return this.a.fromBufferAttribute(t,e),this.b.fromBufferAttribute(t,i),this.c.fromBufferAttribute(t,n),this}clone(){return(new this.constructor).copy(this)}copy(t){return this.a.copy(t.a),this.b.copy(t.b),this.c.copy(t.c),this}getArea(){return ai.subVectors(this.c,this.b),oi.subVectors(this.a,this.b),.5*ai.cross(oi).length()}getMidpoint(t){return t.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(t){return gi.getNormal(this.a,this.b,this.c,t)}getPlane(t){return t.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(t,e){return gi.getBarycoord(t,this.a,this.b,this.c,e)}getUV(t,e,i,n,r){return gi.getUV(t,this.a,this.b,this.c,e,i,n,r)}containsPoint(t){return gi.containsPoint(t,this.a,this.b,this.c)}isFrontFacing(t){return gi.isFrontFacing(this.a,this.b,this.c,t)}intersectsBox(t){return t.intersectsTriangle(this)}closestPointToPoint(t,e){const i=this.a,n=this.b,r=this.c;let s,a;hi.subVectors(n,i),ui.subVectors(r,i),pi.subVectors(t,i);const o=hi.dot(pi),l=ui.dot(pi);if(o<=0&&l<=0)return e.copy(i);mi.subVectors(t,n);const c=hi.dot(mi),h=ui.dot(mi);if(c>=0&&h<=c)return e.copy(n);const u=o*h-c*l;if(u<=0&&o>=0&&c<=0)return s=o/(o-c),e.copy(i).addScaledVector(hi,s);fi.subVectors(t,r);const d=hi.dot(fi),p=ui.dot(fi);if(p>=0&&d<=p)return e.copy(r);const m=d*l-o*p;if(m<=0&&l>=0&&p<=0)return a=l/(l-p),e.copy(i).addScaledVector(ui,a);const f=c*p-d*h;if(f<=0&&h-c>=0&&d-p>=0)return di.subVectors(r,n),a=(h-c)/(h-c+(d-p)),e.copy(n).addScaledVector(di,a);const g=1/(f+m+u);return s=m*g,a=u*g,e.copy(i).addScaledVector(hi,s).addScaledVector(ui,a)}equals(t){return t.a.equals(this.a)&&t.b.equals(this.b)&&t.c.equals(this.c)}}let vi=0;class xi extends mt{constructor(){super(),this.isMaterial=!0,Object.defineProperty(this,"id",{value:vi++}),this.uuid=_t(),this.name="",this.type="Material",this.blending=1,this.side=0,this.vertexColors=!1,this.opacity=1,this.transparent=!1,this.blendSrc=204,this.blendDst=205,this.blendEquation=i,this.blendSrcAlpha=null,this.blendDstAlpha=null,this.blendEquationAlpha=null,this.depthFunc=3,this.depthTest=!0,this.depthWrite=!0,this.stencilWriteMask=255,this.stencilFunc=519,this.stencilRef=0,this.stencilFuncMask=255,this.stencilFail=ht,this.stencilZFail=ht,this.stencilZPass=ht,this.stencilWrite=!1,this.clippingPlanes=null,this.clipIntersection=!1,this.clipShadows=!1,this.shadowSide=null,this.colorWrite=!0,this.precision=null,this.polygonOffset=!1,this.polygonOffsetFactor=0,this.polygonOffsetUnits=0,this.dithering=!1,this.alphaToCoverage=!1,this.premultipliedAlpha=!1,this.visible=!0,this.toneMapped=!0,this.userData={},this.version=0,this._alphaTest=0}get alphaTest(){return this._alphaTest}set alphaTest(t){this._alphaTest>0!=t>0&&this.version++,this._alphaTest=t}onBuild(){}onBeforeRender(){}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(t){if(void 0!==t)for(const e in t){const i=t[e];if(void 0===i){console.warn("THREE.Material: '"+e+"' parameter is undefined.");continue}const n=this[e];void 0!==n?n&&n.isColor?n.set(i):n&&n.isVector3&&i&&i.isVector3?n.copy(i):this[e]=i:console.warn("THREE."+this.type+": '"+e+"' is not a property of this material.")}}toJSON(t){const e=void 0===t||"string"==typeof t;e&&(t={textures:{},images:{}});const i={metadata:{version:4.5,type:"Material",generator:"Material.toJSON"}};function n(t){const e=[];for(const i in t){const n=t[i];delete n.metadata,e.push(n)}return e}if(i.uuid=this.uuid,i.type=this.type,""!==this.name&&(i.name=this.name),this.color&&this.color.isColor&&(i.color=this.color.getHex()),void 0!==this.roughness&&(i.roughness=this.roughness),void 0!==this.metalness&&(i.metalness=this.metalness),void 0!==this.sheen&&(i.sheen=this.sheen),this.sheenColor&&this.sheenColor.isColor&&(i.sheenColor=this.sheenColor.getHex()),void 0!==this.sheenRoughness&&(i.sheenRoughness=this.sheenRoughness),this.emissive&&this.emissive.isColor&&(i.emissive=this.emissive.getHex()),this.emissiveIntensity&&1!==this.emissiveIntensity&&(i.emissiveIntensity=this.emissiveIntensity),this.specular&&this.specular.isColor&&(i.specular=this.specular.getHex()),void 0!==this.specularIntensity&&(i.specularIntensity=this.specularIntensity),this.specularColor&&this.specularColor.isColor&&(i.specularColor=this.specularColor.getHex()),void 0!==this.shininess&&(i.shininess=this.shininess),void 0!==this.clearcoat&&(i.clearcoat=this.clearcoat),void 0!==this.clearcoatRoughness&&(i.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&&this.clearcoatMap.isTexture&&(i.clearcoatMap=this.clearcoatMap.toJSON(t).uuid),this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture&&(i.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(t).uuid),this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture&&(i.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(t).uuid,i.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),void 0!==this.iridescence&&(i.iridescence=this.iridescence),void 0!==this.iridescenceIOR&&(i.iridescenceIOR=this.iridescenceIOR),void 0!==this.iridescenceThicknessRange&&(i.iridescenceThicknessRange=this.iridescenceThicknessRange),this.iridescenceMap&&this.iridescenceMap.isTexture&&(i.iridescenceMap=this.iridescenceMap.toJSON(t).uuid),this.iridescenceThicknessMap&&this.iridescenceThicknessMap.isTexture&&(i.iridescenceThicknessMap=this.iridescenceThicknessMap.toJSON(t).uuid),this.map&&this.map.isTexture&&(i.map=this.map.toJSON(t).uuid),this.matcap&&this.matcap.isTexture&&(i.matcap=this.matcap.toJSON(t).uuid),this.alphaMap&&this.alphaMap.isTexture&&(i.alphaMap=this.alphaMap.toJSON(t).uuid),this.lightMap&&this.lightMap.isTexture&&(i.lightMap=this.lightMap.toJSON(t).uuid,i.lightMapIntensity=this.lightMapIntensity),this.aoMap&&this.aoMap.isTexture&&(i.aoMap=this.aoMap.toJSON(t).uuid,i.aoMapIntensity=this.aoMapIntensity),this.bumpMap&&this.bumpMap.isTexture&&(i.bumpMap=this.bumpMap.toJSON(t).uuid,i.bumpScale=this.bumpScale),this.normalMap&&this.normalMap.isTexture&&(i.normalMap=this.normalMap.toJSON(t).uuid,i.normalMapType=this.normalMapType,i.normalScale=this.normalScale.toArray()),this.displacementMap&&this.displacementMap.isTexture&&(i.displacementMap=this.displacementMap.toJSON(t).uuid,i.displacementScale=this.displacementScale,i.displacementBias=this.displacementBias),this.roughnessMap&&this.roughnessMap.isTexture&&(i.roughnessMap=this.roughnessMap.toJSON(t).uuid),this.metalnessMap&&this.metalnessMap.isTexture&&(i.metalnessMap=this.metalnessMap.toJSON(t).uuid),this.emissiveMap&&this.emissiveMap.isTexture&&(i.emissiveMap=this.emissiveMap.toJSON(t).uuid),this.specularMap&&this.specularMap.isTexture&&(i.specularMap=this.specularMap.toJSON(t).uuid),this.specularIntensityMap&&this.specularIntensityMap.isTexture&&(i.specularIntensityMap=this.specularIntensityMap.toJSON(t).uuid),this.specularColorMap&&this.specularColorMap.isTexture&&(i.specularColorMap=this.specularColorMap.toJSON(t).uuid),this.envMap&&this.envMap.isTexture&&(i.envMap=this.envMap.toJSON(t).uuid,void 0!==this.combine&&(i.combine=this.combine)),void 0!==this.envMapIntensity&&(i.envMapIntensity=this.envMapIntensity),void 0!==this.reflectivity&&(i.reflectivity=this.reflectivity),void 0!==this.refractionRatio&&(i.refractionRatio=this.refractionRatio),this.gradientMap&&this.gradientMap.isTexture&&(i.gradientMap=this.gradientMap.toJSON(t).uuid),void 0!==this.transmission&&(i.transmission=this.transmission),this.transmissionMap&&this.transmissionMap.isTexture&&(i.transmissionMap=this.transmissionMap.toJSON(t).uuid),void 0!==this.thickness&&(i.thickness=this.thickness),this.thicknessMap&&this.thicknessMap.isTexture&&(i.thicknessMap=this.thicknessMap.toJSON(t).uuid),void 0!==this.attenuationDistance&&this.attenuationDistance!==1/0&&(i.attenuationDistance=this.attenuationDistance),void 0!==this.attenuationColor&&(i.attenuationColor=this.attenuationColor.getHex()),void 0!==this.size&&(i.size=this.size),null!==this.shadowSide&&(i.shadowSide=this.shadowSide),void 0!==this.sizeAttenuation&&(i.sizeAttenuation=this.sizeAttenuation),1!==this.blending&&(i.blending=this.blending),0!==this.side&&(i.side=this.side),this.vertexColors&&(i.vertexColors=!0),this.opacity<1&&(i.opacity=this.opacity),!0===this.transparent&&(i.transparent=this.transparent),i.depthFunc=this.depthFunc,i.depthTest=this.depthTest,i.depthWrite=this.depthWrite,i.colorWrite=this.colorWrite,i.stencilWrite=this.stencilWrite,i.stencilWriteMask=this.stencilWriteMask,i.stencilFunc=this.stencilFunc,i.stencilRef=this.stencilRef,i.stencilFuncMask=this.stencilFuncMask,i.stencilFail=this.stencilFail,i.stencilZFail=this.stencilZFail,i.stencilZPass=this.stencilZPass,void 0!==this.rotation&&0!==this.rotation&&(i.rotation=this.rotation),!0===this.polygonOffset&&(i.polygonOffset=!0),0!==this.polygonOffsetFactor&&(i.polygonOffsetFactor=this.polygonOffsetFactor),0!==this.polygonOffsetUnits&&(i.polygonOffsetUnits=this.polygonOffsetUnits),void 0!==this.linewidth&&1!==this.linewidth&&(i.linewidth=this.linewidth),void 0!==this.dashSize&&(i.dashSize=this.dashSize),void 0!==this.gapSize&&(i.gapSize=this.gapSize),void 0!==this.scale&&(i.scale=this.scale),!0===this.dithering&&(i.dithering=!0),this.alphaTest>0&&(i.alphaTest=this.alphaTest),!0===this.alphaToCoverage&&(i.alphaToCoverage=this.alphaToCoverage),!0===this.premultipliedAlpha&&(i.premultipliedAlpha=this.premultipliedAlpha),!0===this.wireframe&&(i.wireframe=this.wireframe),this.wireframeLinewidth>1&&(i.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(i.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(i.wireframeLinejoin=this.wireframeLinejoin),!0===this.flatShading&&(i.flatShading=this.flatShading),!1===this.visible&&(i.visible=!1),!1===this.toneMapped&&(i.toneMapped=!1),!1===this.fog&&(i.fog=!1),"{}"!==JSON.stringify(this.userData)&&(i.userData=this.userData),e){const e=n(t.textures),r=n(t.images);e.length>0&&(i.textures=e),r.length>0&&(i.images=r)}return i}clone(){return(new this.constructor).copy(this)}copy(t){this.name=t.name,this.blending=t.blending,this.side=t.side,this.vertexColors=t.vertexColors,this.opacity=t.opacity,this.transparent=t.transparent,this.blendSrc=t.blendSrc,this.blendDst=t.blendDst,this.blendEquation=t.blendEquation,this.blendSrcAlpha=t.blendSrcAlpha,this.blendDstAlpha=t.blendDstAlpha,this.blendEquationAlpha=t.blendEquationAlpha,this.depthFunc=t.depthFunc,this.depthTest=t.depthTest,this.depthWrite=t.depthWrite,this.stencilWriteMask=t.stencilWriteMask,this.stencilFunc=t.stencilFunc,this.stencilRef=t.stencilRef,this.stencilFuncMask=t.stencilFuncMask,this.stencilFail=t.stencilFail,this.stencilZFail=t.stencilZFail,this.stencilZPass=t.stencilZPass,this.stencilWrite=t.stencilWrite;const e=t.clippingPlanes;let i=null;if(null!==e){const t=e.length;i=new Array(t);for(let n=0;n!==t;++n)i[n]=e[n].clone()}return this.clippingPlanes=i,this.clipIntersection=t.clipIntersection,this.clipShadows=t.clipShadows,this.shadowSide=t.shadowSide,this.colorWrite=t.colorWrite,this.precision=t.precision,this.polygonOffset=t.polygonOffset,this.polygonOffsetFactor=t.polygonOffsetFactor,this.polygonOffsetUnits=t.polygonOffsetUnits,this.dithering=t.dithering,this.alphaTest=t.alphaTest,this.alphaToCoverage=t.alphaToCoverage,this.premultipliedAlpha=t.premultipliedAlpha,this.visible=t.visible,this.toneMapped=t.toneMapped,this.userData=JSON.parse(JSON.stringify(t.userData)),this}dispose(){this.dispatchEvent({type:"dispose"})}set needsUpdate(t){!0===t&&this.version++}}class _i extends xi{constructor(t){super(),this.isMeshBasicMaterial=!0,this.type="MeshBasicMaterial",this.color=new qt(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.fog=t.fog,this}}const yi=new re,Mi=new Lt;class bi{constructor(t,e,i){if(Array.isArray(t))throw new TypeError("THREE.BufferAttribute: array should be a Typed Array.");this.isBufferAttribute=!0,this.name="",this.array=t,this.itemSize=e,this.count=void 0!==t?t.length/e:0,this.normalized=!0===i,this.usage=ut,this.updateRange={offset:0,count:-1},this.version=0}onUploadCallback(){}set needsUpdate(t){!0===t&&this.version++}setUsage(t){return this.usage=t,this}copy(t){return this.name=t.name,this.array=new t.array.constructor(t.array),this.itemSize=t.itemSize,this.count=t.count,this.normalized=t.normalized,this.usage=t.usage,this}copyAt(t,e,i){t*=this.itemSize,i*=e.itemSize;for(let n=0,r=this.itemSize;n0&&(t.userData=this.userData),void 0!==this.parameters){const e=this.parameters;for(const i in e)void 0!==e[i]&&(t[i]=e[i]);return t}t.data={attributes:{}};const e=this.index;null!==e&&(t.data.index={type:e.array.constructor.name,array:Array.prototype.slice.call(e.array)});const i=this.attributes;for(const e in i){const n=i[e];t.data.attributes[e]=n.toJSON(t.data)}const n={};let r=!1;for(const e in this.morphAttributes){const i=this.morphAttributes[e],s=[];for(let e=0,n=i.length;e0&&(n[e]=s,r=!0)}r&&(t.data.morphAttributes=n,t.data.morphTargetsRelative=this.morphTargetsRelative);const s=this.groups;s.length>0&&(t.data.groups=JSON.parse(JSON.stringify(s)));const a=this.boundingSphere;return null!==a&&(t.data.boundingSphere={center:a.center.toArray(),radius:a.radius}),t}clone(){return(new this.constructor).copy(this)}copy(t){this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null;const e={};this.name=t.name;const i=t.index;null!==i&&this.setIndex(i.clone(e));const n=t.attributes;for(const t in n){const i=n[t];this.setAttribute(t,i.clone(e))}const r=t.morphAttributes;for(const t in r){const i=[],n=r[t];for(let t=0,r=n.length;t0){const i=t[e[0]];if(void 0!==i){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=i.length;ti.far?null:{distance:c,point:Ji.clone(),object:t}}(t,e,i,n,Ui,Bi,Fi,Zi);if(p){o&&(qi.fromBufferAttribute(o,c),Xi.fromBufferAttribute(o,h),Yi.fromBufferAttribute(o,u),p.uv=gi.getUV(Zi,Ui,Bi,Fi,qi,Xi,Yi,new Lt)),l&&(qi.fromBufferAttribute(l,c),Xi.fromBufferAttribute(l,h),Yi.fromBufferAttribute(l,u),p.uv2=gi.getUV(Zi,Ui,Bi,Fi,qi,Xi,Yi,new Lt));const t={a:c,b:h,c:u,normal:new re,materialIndex:0};gi.getNormal(Ui,Bi,Fi,t.normal),p.face=t}return p}class Qi extends Di{constructor(t=1,e=1,i=1,n=1,r=1,s=1){super(),this.type="BoxGeometry",this.parameters={width:t,height:e,depth:i,widthSegments:n,heightSegments:r,depthSegments:s};const a=this;n=Math.floor(n),r=Math.floor(r),s=Math.floor(s);const o=[],l=[],c=[],h=[];let u=0,d=0;function p(t,e,i,n,r,s,p,m,f,g,v){const x=s/f,_=p/g,y=s/2,M=p/2,b=m/2,w=f+1,S=g+1;let T=0,A=0;const E=new re;for(let s=0;s0?1:-1,c.push(E.x,E.y,E.z),h.push(o/f),h.push(1-s/g),T+=1}}for(let t=0;t0&&(e.defines=this.defines),e.vertexShader=this.vertexShader,e.fragmentShader=this.fragmentShader;const i={};for(const t in this.extensions)!0===this.extensions[t]&&(i[t]=!0);return Object.keys(i).length>0&&(e.extensions=i),e}}class an extends si{constructor(){super(),this.isCamera=!0,this.type="Camera",this.matrixWorldInverse=new Ne,this.projectionMatrix=new Ne,this.projectionMatrixInverse=new Ne}copy(t,e){return super.copy(t,e),this.matrixWorldInverse.copy(t.matrixWorldInverse),this.projectionMatrix.copy(t.projectionMatrix),this.projectionMatrixInverse.copy(t.projectionMatrixInverse),this}getWorldDirection(t){this.updateWorldMatrix(!0,!1);const e=this.matrixWorld.elements;return t.set(-e[8],-e[9],-e[10]).normalize()}updateMatrixWorld(t){super.updateMatrixWorld(t),this.matrixWorldInverse.copy(this.matrixWorld).invert()}updateWorldMatrix(t,e){super.updateWorldMatrix(t,e),this.matrixWorldInverse.copy(this.matrixWorld).invert()}clone(){return(new this.constructor).copy(this)}}class on extends an{constructor(t=50,e=1,i=.1,n=2e3){super(),this.isPerspectiveCamera=!0,this.type="PerspectiveCamera",this.fov=t,this.zoom=1,this.near=i,this.far=n,this.focus=10,this.aspect=e,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}copy(t,e){return super.copy(t,e),this.fov=t.fov,this.zoom=t.zoom,this.near=t.near,this.far=t.far,this.focus=t.focus,this.aspect=t.aspect,this.view=null===t.view?null:Object.assign({},t.view),this.filmGauge=t.filmGauge,this.filmOffset=t.filmOffset,this}setFocalLength(t){const e=.5*this.getFilmHeight()/t;this.fov=2*xt*Math.atan(e),this.updateProjectionMatrix()}getFocalLength(){const t=Math.tan(.5*vt*this.fov);return.5*this.getFilmHeight()/t}getEffectiveFOV(){return 2*xt*Math.atan(Math.tan(.5*vt*this.fov)/this.zoom)}getFilmWidth(){return this.filmGauge*Math.min(this.aspect,1)}getFilmHeight(){return this.filmGauge/Math.max(this.aspect,1)}setViewOffset(t,e,i,n,r,s){this.aspect=t/e,null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=i,this.view.offsetY=n,this.view.width=r,this.view.height=s,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const t=this.near;let e=t*Math.tan(.5*vt*this.fov)/this.zoom,i=2*e,n=this.aspect*i,r=-.5*n;const s=this.view;if(null!==this.view&&this.view.enabled){const t=s.fullWidth,a=s.fullHeight;r+=s.offsetX*n/t,e-=s.offsetY*i/a,n*=s.width/t,i*=s.height/a}const a=this.filmOffset;0!==a&&(r+=t*a/this.getFilmWidth()),this.projectionMatrix.makePerspective(r,r+n,e,e-i,t,this.far),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(t){const e=super.toJSON(t);return e.object.fov=this.fov,e.object.zoom=this.zoom,e.object.near=this.near,e.object.far=this.far,e.object.focus=this.focus,e.object.aspect=this.aspect,null!==this.view&&(e.object.view=Object.assign({},this.view)),e.object.filmGauge=this.filmGauge,e.object.filmOffset=this.filmOffset,e}}const ln=-90;class cn extends si{constructor(t,e,i){super(),this.type="CubeCamera",this.renderTarget=i;const n=new on(ln,1,t,e);n.layers=this.layers,n.up.set(0,1,0),n.lookAt(1,0,0),this.add(n);const r=new on(ln,1,t,e);r.layers=this.layers,r.up.set(0,1,0),r.lookAt(-1,0,0),this.add(r);const s=new on(ln,1,t,e);s.layers=this.layers,s.up.set(0,0,-1),s.lookAt(0,1,0),this.add(s);const a=new on(ln,1,t,e);a.layers=this.layers,a.up.set(0,0,1),a.lookAt(0,-1,0),this.add(a);const o=new on(ln,1,t,e);o.layers=this.layers,o.up.set(0,1,0),o.lookAt(0,0,1),this.add(o);const l=new on(ln,1,t,e);l.layers=this.layers,l.up.set(0,1,0),l.lookAt(0,0,-1),this.add(l)}update(t,e){null===this.parent&&this.updateMatrixWorld();const i=this.renderTarget,[n,r,s,a,o,l]=this.children,c=t.getRenderTarget(),h=t.toneMapping,u=t.xr.enabled;t.toneMapping=0,t.xr.enabled=!1;const d=i.texture.generateMipmaps;i.texture.generateMipmaps=!1,t.setRenderTarget(i,0),t.render(e,n),t.setRenderTarget(i,1),t.render(e,r),t.setRenderTarget(i,2),t.render(e,s),t.setRenderTarget(i,3),t.render(e,a),t.setRenderTarget(i,4),t.render(e,o),i.texture.generateMipmaps=d,t.setRenderTarget(i,5),t.render(e,l),t.setRenderTarget(c),t.toneMapping=h,t.xr.enabled=u,i.texture.needsPMREMUpdate=!0}}class hn extends $t{constructor(t,e,i,n,s,a,o,l,c,h){super(t=void 0!==t?t:[],e=void 0!==e?e:r,i,n,s,a,o,l,c,h),this.isCubeTexture=!0,this.flipY=!1}get images(){return this.image}set images(t){this.image=t}}class un extends te{constructor(t=1,e={}){super(t,t,e),this.isWebGLCubeRenderTarget=!0;const i={width:t,height:t,depth:1},n=[i,i,i,i,i,i];this.texture=new hn(n,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.encoding),this.texture.isRenderTargetTexture=!0,this.texture.generateMipmaps=void 0!==e.generateMipmaps&&e.generateMipmaps,this.texture.minFilter=void 0!==e.minFilter?e.minFilter:f}fromEquirectangularTexture(t,e){this.texture.type=e.type,this.texture.encoding=e.encoding,this.texture.generateMipmaps=e.generateMipmaps,this.texture.minFilter=e.minFilter,this.texture.magFilter=e.magFilter;const i={uniforms:{tEquirect:{value:null}},vertexShader:"\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\tvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\n\t\t\t\t\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n\n\t\t\t\t}\n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvWorldDirection = transformDirection( position, modelMatrix );\n\n\t\t\t\t\t#include \n\t\t\t\t\t#include \n\n\t\t\t\t}\n\t\t\t",fragmentShader:"\n\n\t\t\t\tuniform sampler2D tEquirect;\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\t#include \n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvec3 direction = normalize( vWorldDirection );\n\n\t\t\t\t\tvec2 sampleUV = equirectUv( direction );\n\n\t\t\t\t\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\n\t\t\t\t}\n\t\t\t"},n=new Qi(5,5,5),r=new sn({name:"CubemapFromEquirect",uniforms:tn(i.uniforms),vertexShader:i.vertexShader,fragmentShader:i.fragmentShader,side:1,blending:0});r.uniforms.tEquirect.value=e;const s=new Ki(n,r),a=e.minFilter;e.minFilter===v&&(e.minFilter=f);return new cn(1,10,this).update(t,s),e.minFilter=a,s.geometry.dispose(),s.material.dispose(),this}clear(t,e,i,n){const r=t.getRenderTarget();for(let r=0;r<6;r++)t.setRenderTarget(this,r),t.clear(e,i,n);t.setRenderTarget(r)}}const dn=new re,pn=new re,mn=new Rt;class fn{constructor(t=new re(1,0,0),e=0){this.isPlane=!0,this.normal=t,this.constant=e}set(t,e){return this.normal.copy(t),this.constant=e,this}setComponents(t,e,i,n){return this.normal.set(t,e,i),this.constant=n,this}setFromNormalAndCoplanarPoint(t,e){return this.normal.copy(t),this.constant=-e.dot(this.normal),this}setFromCoplanarPoints(t,e,i){const n=dn.subVectors(i,e).cross(pn.subVectors(t,e)).normalize();return this.setFromNormalAndCoplanarPoint(n,t),this}copy(t){return this.normal.copy(t.normal),this.constant=t.constant,this}normalize(){const t=1/this.normal.length();return this.normal.multiplyScalar(t),this.constant*=t,this}negate(){return this.constant*=-1,this.normal.negate(),this}distanceToPoint(t){return this.normal.dot(t)+this.constant}distanceToSphere(t){return this.distanceToPoint(t.center)-t.radius}projectPoint(t,e){return e.copy(this.normal).multiplyScalar(-this.distanceToPoint(t)).add(t)}intersectLine(t,e){const i=t.delta(dn),n=this.normal.dot(i);if(0===n)return 0===this.distanceToPoint(t.start)?e.copy(t.start):null;const r=-(t.start.dot(this.normal)+this.constant)/n;return r<0||r>1?null:e.copy(i).multiplyScalar(r).add(t.start)}intersectsLine(t){const e=this.distanceToPoint(t.start),i=this.distanceToPoint(t.end);return e<0&&i>0||i<0&&e>0}intersectsBox(t){return t.intersectsPlane(this)}intersectsSphere(t){return t.intersectsPlane(this)}coplanarPoint(t){return t.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(t,e){const i=e||mn.getNormalMatrix(t),n=this.coplanarPoint(dn).applyMatrix4(t),r=this.normal.applyMatrix3(i).normalize();return this.constant=-n.dot(r),this}translate(t){return this.constant-=t.dot(this.normal),this}equals(t){return t.normal.equals(this.normal)&&t.constant===this.constant}clone(){return(new this.constructor).copy(this)}}const gn=new Te,vn=new re;class xn{constructor(t=new fn,e=new fn,i=new fn,n=new fn,r=new fn,s=new fn){this.planes=[t,e,i,n,r,s]}set(t,e,i,n,r,s){const a=this.planes;return a[0].copy(t),a[1].copy(e),a[2].copy(i),a[3].copy(n),a[4].copy(r),a[5].copy(s),this}copy(t){const e=this.planes;for(let i=0;i<6;i++)e[i].copy(t.planes[i]);return this}setFromProjectionMatrix(t){const e=this.planes,i=t.elements,n=i[0],r=i[1],s=i[2],a=i[3],o=i[4],l=i[5],c=i[6],h=i[7],u=i[8],d=i[9],p=i[10],m=i[11],f=i[12],g=i[13],v=i[14],x=i[15];return e[0].setComponents(a-n,h-o,m-u,x-f).normalize(),e[1].setComponents(a+n,h+o,m+u,x+f).normalize(),e[2].setComponents(a+r,h+l,m+d,x+g).normalize(),e[3].setComponents(a-r,h-l,m-d,x-g).normalize(),e[4].setComponents(a-s,h-c,m-p,x-v).normalize(),e[5].setComponents(a+s,h+c,m+p,x+v).normalize(),this}intersectsObject(t){const e=t.geometry;return null===e.boundingSphere&&e.computeBoundingSphere(),gn.copy(e.boundingSphere).applyMatrix4(t.matrixWorld),this.intersectsSphere(gn)}intersectsSprite(t){return gn.center.set(0,0,0),gn.radius=.7071067811865476,gn.applyMatrix4(t.matrixWorld),this.intersectsSphere(gn)}intersectsSphere(t){const e=this.planes,i=t.center,n=-t.radius;for(let t=0;t<6;t++){if(e[t].distanceToPoint(i)0?t.max.x:t.min.x,vn.y=n.normal.y>0?t.max.y:t.min.y,vn.z=n.normal.z>0?t.max.z:t.min.z,n.distanceToPoint(vn)<0)return!1}return!0}containsPoint(t){const e=this.planes;for(let i=0;i<6;i++)if(e[i].distanceToPoint(t)<0)return!1;return!0}clone(){return(new this.constructor).copy(this)}}function _n(){let t=null,e=!1,i=null,n=null;function r(e,s){i(e,s),n=t.requestAnimationFrame(r)}return{start:function(){!0!==e&&null!==i&&(n=t.requestAnimationFrame(r),e=!0)},stop:function(){t.cancelAnimationFrame(n),e=!1},setAnimationLoop:function(t){i=t},setContext:function(e){t=e}}}function yn(t,e){const i=e.isWebGL2,n=new WeakMap;return{get:function(t){return t.isInterleavedBufferAttribute&&(t=t.data),n.get(t)},remove:function(e){e.isInterleavedBufferAttribute&&(e=e.data);const i=n.get(e);i&&(t.deleteBuffer(i.buffer),n.delete(e))},update:function(e,r){if(e.isGLBufferAttribute){const t=n.get(e);return void((!t||t.version 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, 1.0, dotVH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif",iridescence_fragment:"#ifdef USE_IRIDESCENCE\n\tconst mat3 XYZ_TO_REC709 = mat3(\n\t\t 3.2404542, -0.9692660,\t0.0556434,\n\t\t-1.5371385,\t1.8760108, -0.2040259,\n\t\t-0.4985314,\t0.0415560,\t1.0572252\n\t);\n\tvec3 Fresnel0ToIor( vec3 fresnel0 ) {\n\t\tvec3 sqrtF0 = sqrt( fresnel0 );\n\t\treturn ( vec3( 1.0 ) + sqrtF0 ) / ( vec3( 1.0 ) - sqrtF0 );\n\t}\n\tvec3 IorToFresnel0( vec3 transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - vec3( incidentIor ) ) / ( transmittedIor + vec3( incidentIor ) ) );\n\t}\n\tfloat IorToFresnel0( float transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - incidentIor ) / ( transmittedIor + incidentIor ));\n\t}\n\tvec3 evalSensitivity( float OPD, vec3 shift ) {\n\t\tfloat phase = 2.0 * PI * OPD * 1.0e-9;\n\t\tvec3 val = vec3( 5.4856e-13, 4.4201e-13, 5.2481e-13 );\n\t\tvec3 pos = vec3( 1.6810e+06, 1.7953e+06, 2.2084e+06 );\n\t\tvec3 var = vec3( 4.3278e+09, 9.3046e+09, 6.6121e+09 );\n\t\tvec3 xyz = val * sqrt( 2.0 * PI * var ) * cos( pos * phase + shift ) * exp( - pow2( phase ) * var );\n\t\txyz.x += 9.7470e-14 * sqrt( 2.0 * PI * 4.5282e+09 ) * cos( 2.2399e+06 * phase + shift[ 0 ] ) * exp( - 4.5282e+09 * pow2( phase ) );\n\t\txyz /= 1.0685e-7;\n\t\tvec3 rgb = XYZ_TO_REC709 * xyz;\n\t\treturn rgb;\n\t}\n\tvec3 evalIridescence( float outsideIOR, float eta2, float cosTheta1, float thinFilmThickness, vec3 baseF0 ) {\n\t\tvec3 I;\n\t\tfloat iridescenceIOR = mix( outsideIOR, eta2, smoothstep( 0.0, 0.03, thinFilmThickness ) );\n\t\tfloat sinTheta2Sq = pow2( outsideIOR / iridescenceIOR ) * ( 1.0 - pow2( cosTheta1 ) );\n\t\tfloat cosTheta2Sq = 1.0 - sinTheta2Sq;\n\t\tif ( cosTheta2Sq < 0.0 ) {\n\t\t\t return vec3( 1.0 );\n\t\t}\n\t\tfloat cosTheta2 = sqrt( cosTheta2Sq );\n\t\tfloat R0 = IorToFresnel0( iridescenceIOR, outsideIOR );\n\t\tfloat R12 = F_Schlick( R0, 1.0, cosTheta1 );\n\t\tfloat R21 = R12;\n\t\tfloat T121 = 1.0 - R12;\n\t\tfloat phi12 = 0.0;\n\t\tif ( iridescenceIOR < outsideIOR ) phi12 = PI;\n\t\tfloat phi21 = PI - phi12;\n\t\tvec3 baseIOR = Fresnel0ToIor( clamp( baseF0, 0.0, 0.9999 ) );\t\tvec3 R1 = IorToFresnel0( baseIOR, iridescenceIOR );\n\t\tvec3 R23 = F_Schlick( R1, 1.0, cosTheta2 );\n\t\tvec3 phi23 = vec3( 0.0 );\n\t\tif ( baseIOR[ 0 ] < iridescenceIOR ) phi23[ 0 ] = PI;\n\t\tif ( baseIOR[ 1 ] < iridescenceIOR ) phi23[ 1 ] = PI;\n\t\tif ( baseIOR[ 2 ] < iridescenceIOR ) phi23[ 2 ] = PI;\n\t\tfloat OPD = 2.0 * iridescenceIOR * thinFilmThickness * cosTheta2;\n\t\tvec3 phi = vec3( phi21 ) + phi23;\n\t\tvec3 R123 = clamp( R12 * R23, 1e-5, 0.9999 );\n\t\tvec3 r123 = sqrt( R123 );\n\t\tvec3 Rs = pow2( T121 ) * R23 / ( vec3( 1.0 ) - R123 );\n\t\tvec3 C0 = R12 + Rs;\n\t\tI = C0;\n\t\tvec3 Cm = Rs - T121;\n\t\tfor ( int m = 1; m <= 2; ++ m ) {\n\t\t\tCm *= r123;\n\t\t\tvec3 Sm = 2.0 * evalSensitivity( float( m ) * OPD, float( m ) * phi );\n\t\t\tI += Cm * Sm;\n\t\t}\n\t\treturn max( I, vec3( 0.0 ) );\n\t}\n#endif",bumpmap_pars_fragment:"#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) {\n\t\tvec3 vSigmaX = dFdx( surf_pos.xyz );\n\t\tvec3 vSigmaY = dFdy( surf_pos.xyz );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 ) * faceDirection;\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif",clipping_planes_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#pragma unroll_loop_end\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\tif ( clipped ) discard;\n\t#endif\n#endif",clipping_planes_pars_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif",clipping_planes_pars_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif",clipping_planes_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif",color_fragment:"#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif",color_pars_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvarying vec3 vColor;\n#endif",color_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif",common:"#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nvec3 pow2( const in vec3 x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat luminance( const in vec3 rgb ) {\n\tconst vec3 weights = vec3( 0.2126729, 0.7151522, 0.0721750 );\n\treturn dot( weights, rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}",cube_uv_reflection_fragment:"#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\tvec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tuv.x += filterInt * 3.0 * cubeUV_minTileSize;\n\t\tuv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n\t\tuv.x *= CUBEUV_TEXEL_WIDTH;\n\t\tuv.y *= CUBEUV_TEXEL_HEIGHT;\n\t\t#ifdef texture2DGradEXT\n\t\t\treturn texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n\t\t#else\n\t\t\treturn texture2D( envMap, uv ).rgb;\n\t\t#endif\n\t}\n\t#define cubeUV_r0 1.0\n\t#define cubeUV_v0 0.339\n\t#define cubeUV_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_v1 0.276\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_v4 0.046\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_v5 0.016\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\n\t#define cubeUV_v6 0.0038\n\t#define cubeUV_m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= cubeUV_r1 ) {\n\t\t\tmip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0;\n\t\t} else if ( roughness >= cubeUV_r4 ) {\n\t\t\tmip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1;\n\t\t} else if ( roughness >= cubeUV_r5 ) {\n\t\t\tmip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4;\n\t\t} else if ( roughness >= cubeUV_r6 ) {\n\t\t\tmip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif",defaultnormal_vertex:"vec3 transformedNormal = objectNormal;\n#ifdef USE_INSTANCING\n\tmat3 m = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) );\n\ttransformedNormal = m * transformedNormal;\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\n#endif",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif",encodings_fragment:"gl_FragColor = linearToOutputTexel( gl_FragColor );",encodings_pars_fragment:"vec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}",envmap_fragment:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif",envmap_common_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif",envmap_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif",envmap_pars_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif",envmap_physical_pars_fragment:"#if defined( USE_ENVMAP )\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n#endif",envmap_vertex:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif",fog_vertex:"#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, vFogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif",fog_pars_fragment:"#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float vFogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif",gradientmap_pars_fragment:"#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\tvec2 fw = fwidth( coord ) * 0.5;\n\t\treturn mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) );\n\t#endif\n}",lightmap_fragment:"#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif",lightmap_pars_fragment:"#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif",lights_lambert_fragment:"LambertMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularStrength = specularStrength;",lights_lambert_pars_fragment:"varying vec3 vViewPosition;\nstruct LambertMaterial {\n\tvec3 diffuseColor;\n\tfloat specularStrength;\n};\nvoid RE_Direct_Lambert( const in IncidentLight directLight, const in GeometricContext geometry, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in GeometricContext geometry, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Lambert\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Lambert",lights_pars_begin:"uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\t#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tif ( cutoffDistance > 0.0 ) {\n\t\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\t}\n\t\treturn distanceFalloff;\n\t#else\n\t\tif ( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\t\treturn pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t\t}\n\t\treturn 1.0;\n\t#endif\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif",lights_toon_fragment:"ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;",lights_toon_pars_fragment:"varying vec3 vViewPosition;\nstruct ToonMaterial {\n\tvec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon",lights_phong_fragment:"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;",lights_phong_pars_fragment:"varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong",lights_physical_fragment:"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\tmaterial.ior = ior;\n\t#ifdef SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULARINTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vUv ).a;\n\t\t#endif\n\t\t#ifdef USE_SPECULARCOLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vUv ).rgb;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vUv ).a;\n\t#endif\n#endif",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n};\nvec3 clearcoatSpecular = vec3( 0.0 );\nvec3 sheenSpecular = vec3( 0.0 );\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3(\t\t0, 1,\t\t0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecular += ccIrradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.clearcoatNormal, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * BRDF_Sheen( directLight.direction, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\treflectedLight.directSpecular += irradiance * BRDF_GGX_Iridescence( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness );\n\t#else\n\t\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.roughness );\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecular += clearcoatRadiance * EnvironmentBRDF( geometry.clearcoatNormal, geometry.viewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * material.sheenColor * IBLSheenBRDF( geometry.normal, geometry.viewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}",lights_fragment_begin:"\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n#ifdef USE_CLEARCOAT\n\tgeometry.clearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometry.viewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence > 0.0 ) {\n\t\tmaterial.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n\t}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometry, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\tirradiance += getLightProbeIrradiance( lightProbe, geometry.normal );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry.normal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif",lights_fragment_maps:"#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometry.normal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness );\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif",lights_fragment_end:"#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );\n#endif",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t\tvarying float vIsPerspective;\n\t#else\n\t\tuniform float logDepthBufFC;\n\t#endif\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n\t#else\n\t\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\n\t\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\t\tgl_Position.z *= gl_Position.w;\n\t\t}\n\t#endif\n#endif",map_fragment:"#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\tsampledDiffuseColor = vec4( mix( pow( sampledDiffuseColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), sampledDiffuseColor.rgb * 0.0773993808, vec3( lessThanEqual( sampledDiffuseColor.rgb, vec3( 0.04045 ) ) ) ), sampledDiffuseColor.w );\n\t#endif\n\tdiffuseColor *= sampledDiffuseColor;\n#endif",map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif",map_particle_fragment:"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif",map_particle_pars_fragment:"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tuniform mat3 uvTransform;\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif",metalnessmap_fragment:"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphcolor_vertex:"#if defined( USE_MORPHCOLORS ) && defined( MORPHTARGETS_TEXTURE )\n\tvColor *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t#if defined( USE_COLOR_ALPHA )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];\n\t\t#elif defined( USE_COLOR )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];\n\t\t#endif\n\t}\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\t\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\t\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\t\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n\t#endif\n#endif",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t\tuniform sampler2DArray morphTargetsTexture;\n\t\tuniform ivec2 morphTargetsTextureSize;\n\t\tvec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n\t\t\tint texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n\t\t\tint y = texelIndex / morphTargetsTextureSize.x;\n\t\t\tint x = texelIndex - y * morphTargetsTextureSize.x;\n\t\t\tivec3 morphUV = ivec3( x, y, morphTargetIndex );\n\t\t\treturn texelFetch( morphTargetsTexture, morphUV, 0 );\n\t\t}\n\t#else\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\tuniform float morphTargetInfluences[ 8 ];\n\t\t#else\n\t\t\tuniform float morphTargetInfluences[ 4 ];\n\t\t#endif\n\t#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\t\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\t\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\t\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t\t#endif\n\t#endif\n#endif",normal_fragment_begin:"float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = dFdx( vViewPosition );\n\tvec3 fdy = dFdy( vViewPosition );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\t#ifdef USE_TANGENT\n\t\tvec3 tangent = normalize( vTangent );\n\t\tvec3 bitangent = normalize( vBitangent );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\ttangent = tangent * faceDirection;\n\t\t\tbitangent = bitangent * faceDirection;\n\t\t#endif\n\t\t#if defined( TANGENTSPACE_NORMALMAP ) || defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tmat3 vTBN = mat3( tangent, bitangent, normal );\n\t\t#endif\n\t#endif\n#endif\nvec3 geometryNormal = normal;",normal_fragment_maps:"#ifdef OBJECTSPACE_NORMALMAP\n\tnormal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( TANGENTSPACE_NORMALMAP )\n\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\t#ifdef USE_TANGENT\n\t\tnormal = normalize( vTBN * mapN );\n\t#else\n\t\tnormal = perturbNormal2Arb( - vViewPosition, normal, mapN, faceDirection );\n\t#endif\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif",normal_pars_fragment:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_pars_vertex:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_vertex:"#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif",normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef OBJECTSPACE_NORMALMAP\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( TANGENTSPACE_NORMALMAP ) || defined ( USE_CLEARCOAT_NORMALMAP ) )\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN, float faceDirection ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : faceDirection * inversesqrt( det );\n\t\treturn normalize( T * ( mapN.x * scale ) + B * ( mapN.y * scale ) + N * mapN.z );\n\t}\n#endif",clearcoat_normal_fragment_begin:"#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = geometryNormal;\n#endif",clearcoat_normal_fragment_maps:"#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\t#ifdef USE_TANGENT\n\t\tclearcoatNormal = normalize( vTBN * clearcoatMapN );\n\t#else\n\t\tclearcoatNormal = perturbNormal2Arb( - vViewPosition, clearcoatNormal, clearcoatMapN, faceDirection );\n\t#endif\n#endif",clearcoat_pars_fragment:"#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif",iridescence_pars_fragment:"#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif",output_fragment:"#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha + 0.1;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );",packing:"vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nvec2 packDepthToRG( in highp float v ) {\n\treturn packDepthToRGBA( v ).yx;\n}\nfloat unpackRGToDepth( const in highp vec2 v ) {\n\treturn unpackRGBAToDepth( vec4( v.xy, 0.0, 0.0 ) );\n}\nvec4 pack2HalfToRGBA( vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}",premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif",project_vertex:"vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;",dithering_fragment:"#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif",dithering_pars_fragment:"#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif",roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t\tf.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t\tf.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif",shadowmap_pars_vertex:"#if NUM_SPOT_LIGHT_COORDS > 0\n\tuniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif",shadowmap_vertex:"#if defined( USE_SHADOWMAP ) || ( NUM_SPOT_LIGHT_COORDS > 0 )\n\t#if NUM_DIR_LIGHT_SHADOWS > 0 || NUM_SPOT_LIGHT_COORDS > 0 || NUM_POINT_LIGHT_SHADOWS > 0\n\t\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\tvec4 shadowWorldPosition;\n\t#endif\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_COORDS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition;\n\t\t#if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t\tshadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias;\n\t\t#endif\n\t\tvSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n#endif",shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}",skinbase_vertex:"#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\tuniform highp sampler2D boneTexture;\n\tuniform int boneTextureSize;\n\tmat4 getBoneMatrix( const in float i ) {\n\t\tfloat j = i * 4.0;\n\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\ty = dy * ( y + 0.5 );\n\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\treturn bone;\n\t}\n#endif",skinning_vertex:"#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif",skinnormal_vertex:"#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif",specularmap_fragment:"float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif",specularmap_pars_fragment:"#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif",tonemapping_fragment:"#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif",tonemapping_pars_fragment:"#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3(\t1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108,\t1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605,\t1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }",transmission_fragment:"#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmission = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmission.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmission.rgb, material.transmission );\n#endif",transmission_pars_fragment:"#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat framebufferLod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\t#ifdef texture2DLodEXT\n\t\t\treturn texture2DLodEXT( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#else\n\t\t\treturn texture2D( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#endif\n\t}\n\tvec3 applyVolumeAttenuation( const in vec3 radiance, const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn radiance;\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance * radiance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 attenuatedColor = applyVolumeAttenuation( transmittedLight.rgb, length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor * diffuseColor, transmittedLight.a );\n\t}\n#endif",uv_pars_fragment:"#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n\tvarying vec2 vUv;\n#endif",uv_pars_vertex:"#ifdef USE_UV\n\t#ifdef UVS_VERTEX_ONLY\n\t\tvec2 vUv;\n\t#else\n\t\tvarying vec2 vUv;\n\t#endif\n\tuniform mat3 uvTransform;\n#endif",uv_vertex:"#ifdef USE_UV\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif",uv2_pars_fragment:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif",uv2_pars_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n\tuniform mat3 uv2Transform;\n#endif",uv2_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif",background_vert:"varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}",background_frag:"uniform sampler2D t2D;\nuniform float backgroundIntensity;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\ttexColor = vec4( mix( pow( texColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), texColor.rgb * 0.0773993808, vec3( lessThanEqual( texColor.rgb, vec3( 0.04045 ) ) ) ), texColor.w );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}",backgroundCube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",backgroundCube_frag:"#ifdef ENVMAP_TYPE_CUBE\n\tuniform samplerCube envMap;\n#elif defined( ENVMAP_TYPE_CUBE_UV )\n\tuniform sampler2D envMap;\n#endif\nuniform float flipEnvMap;\nuniform float backgroundBlurriness;\nuniform float backgroundIntensity;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, vWorldDirection, backgroundBlurriness );\n\t#else\n\t\tvec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}",cube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",cube_frag:"uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldDirection;\nvoid main() {\n\tvec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) );\n\tgl_FragColor = texColor;\n\tgl_FragColor.a *= opacity;\n\t#include \n\t#include \n}",depth_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvHighPrecisionZW = gl_Position.zw;\n}",depth_frag:"#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#endif\n}",distanceRGBA_vert:"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}",distanceRGBA_frag:"#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main () {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}",equirect_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}",equirect_frag:"uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\t#include \n\t#include \n}",linedashed_vert:"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",linedashed_frag:"uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_vert:"#define LAMBERT\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_frag:"#define LAMBERT\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshmatcap_vert:"#define MATCAP\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n}",meshmatcap_frag:"#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#else\n\t\tvec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshnormal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}",meshnormal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}",meshphong_vert:"#define PHONG\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphong_frag:"#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphysical_vert:"#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}",meshphysical_frag:"#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULARINTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n\t#ifdef USE_SPECULARCOLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshtoon_vert:"#define TOON\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}",meshtoon_frag:"#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",points_vert:"uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}",points_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_vert:"#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_frag:"uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n\t#include \n\t#include \n}",sprite_vert:"uniform float rotation;\nuniform vec2 center;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}",sprite_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n}"},wn={common:{diffuse:{value:new qt(16777215)},opacity:{value:1},map:{value:null},uvTransform:{value:new Rt},uv2Transform:{value:new Rt},alphaMap:{value:null},alphaTest:{value:0}},specularmap:{specularMap:{value:null}},envmap:{envMap:{value:null},flipEnvMap:{value:-1},reflectivity:{value:1},ior:{value:1.5},refractionRatio:{value:.98}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1}},emissivemap:{emissiveMap:{value:null}},bumpmap:{bumpMap:{value:null},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalScale:{value:new Lt(1,1)}},displacementmap:{displacementMap:{value:null},displacementScale:{value:1},displacementBias:{value:0}},roughnessmap:{roughnessMap:{value:null}},metalnessmap:{metalnessMap:{value:null}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:25e-5},fogNear:{value:1},fogFar:{value:2e3},fogColor:{value:new qt(16777215)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMap:{value:[]},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},spotLightMap:{value:[]},spotShadowMap:{value:[]},spotLightMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{},shadowCameraNear:{},shadowCameraFar:{}}},pointShadowMap:{value:[]},pointShadowMatrix:{value:[]},hemisphereLights:{value:[],properties:{direction:{},skyColor:{},groundColor:{}}},rectAreaLights:{value:[],properties:{color:{},position:{},width:{},height:{}}},ltc_1:{value:null},ltc_2:{value:null}},points:{diffuse:{value:new qt(16777215)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},alphaTest:{value:0},uvTransform:{value:new Rt}},sprite:{diffuse:{value:new qt(16777215)},opacity:{value:1},center:{value:new Lt(.5,.5)},rotation:{value:0},map:{value:null},alphaMap:{value:null},alphaTest:{value:0},uvTransform:{value:new Rt}}},Sn={basic:{uniforms:en([wn.common,wn.specularmap,wn.envmap,wn.aomap,wn.lightmap,wn.fog]),vertexShader:bn.meshbasic_vert,fragmentShader:bn.meshbasic_frag},lambert:{uniforms:en([wn.common,wn.specularmap,wn.envmap,wn.aomap,wn.lightmap,wn.emissivemap,wn.bumpmap,wn.normalmap,wn.displacementmap,wn.fog,wn.lights,{emissive:{value:new qt(0)}}]),vertexShader:bn.meshlambert_vert,fragmentShader:bn.meshlambert_frag},phong:{uniforms:en([wn.common,wn.specularmap,wn.envmap,wn.aomap,wn.lightmap,wn.emissivemap,wn.bumpmap,wn.normalmap,wn.displacementmap,wn.fog,wn.lights,{emissive:{value:new qt(0)},specular:{value:new qt(1118481)},shininess:{value:30}}]),vertexShader:bn.meshphong_vert,fragmentShader:bn.meshphong_frag},standard:{uniforms:en([wn.common,wn.envmap,wn.aomap,wn.lightmap,wn.emissivemap,wn.bumpmap,wn.normalmap,wn.displacementmap,wn.roughnessmap,wn.metalnessmap,wn.fog,wn.lights,{emissive:{value:new qt(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:bn.meshphysical_vert,fragmentShader:bn.meshphysical_frag},toon:{uniforms:en([wn.common,wn.aomap,wn.lightmap,wn.emissivemap,wn.bumpmap,wn.normalmap,wn.displacementmap,wn.gradientmap,wn.fog,wn.lights,{emissive:{value:new qt(0)}}]),vertexShader:bn.meshtoon_vert,fragmentShader:bn.meshtoon_frag},matcap:{uniforms:en([wn.common,wn.bumpmap,wn.normalmap,wn.displacementmap,wn.fog,{matcap:{value:null}}]),vertexShader:bn.meshmatcap_vert,fragmentShader:bn.meshmatcap_frag},points:{uniforms:en([wn.points,wn.fog]),vertexShader:bn.points_vert,fragmentShader:bn.points_frag},dashed:{uniforms:en([wn.common,wn.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:bn.linedashed_vert,fragmentShader:bn.linedashed_frag},depth:{uniforms:en([wn.common,wn.displacementmap]),vertexShader:bn.depth_vert,fragmentShader:bn.depth_frag},normal:{uniforms:en([wn.common,wn.bumpmap,wn.normalmap,wn.displacementmap,{opacity:{value:1}}]),vertexShader:bn.meshnormal_vert,fragmentShader:bn.meshnormal_frag},sprite:{uniforms:en([wn.sprite,wn.fog]),vertexShader:bn.sprite_vert,fragmentShader:bn.sprite_frag},background:{uniforms:{uvTransform:{value:new Rt},t2D:{value:null},backgroundIntensity:{value:1}},vertexShader:bn.background_vert,fragmentShader:bn.background_frag},backgroundCube:{uniforms:{envMap:{value:null},flipEnvMap:{value:-1},backgroundBlurriness:{value:0},backgroundIntensity:{value:1}},vertexShader:bn.backgroundCube_vert,fragmentShader:bn.backgroundCube_frag},cube:{uniforms:{tCube:{value:null},tFlip:{value:-1},opacity:{value:1}},vertexShader:bn.cube_vert,fragmentShader:bn.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:bn.equirect_vert,fragmentShader:bn.equirect_frag},distanceRGBA:{uniforms:en([wn.common,wn.displacementmap,{referencePosition:{value:new re},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:bn.distanceRGBA_vert,fragmentShader:bn.distanceRGBA_frag},shadow:{uniforms:en([wn.lights,wn.fog,{color:{value:new qt(0)},opacity:{value:1}}]),vertexShader:bn.shadow_vert,fragmentShader:bn.shadow_frag}};Sn.physical={uniforms:en([Sn.standard.uniforms,{clearcoat:{value:0},clearcoatMap:{value:null},clearcoatRoughness:{value:0},clearcoatRoughnessMap:{value:null},clearcoatNormalScale:{value:new Lt(1,1)},clearcoatNormalMap:{value:null},iridescence:{value:0},iridescenceMap:{value:null},iridescenceIOR:{value:1.3},iridescenceThicknessMinimum:{value:100},iridescenceThicknessMaximum:{value:400},iridescenceThicknessMap:{value:null},sheen:{value:0},sheenColor:{value:new qt(0)},sheenColorMap:{value:null},sheenRoughness:{value:1},sheenRoughnessMap:{value:null},transmission:{value:0},transmissionMap:{value:null},transmissionSamplerSize:{value:new Lt},transmissionSamplerMap:{value:null},thickness:{value:0},thicknessMap:{value:null},attenuationDistance:{value:0},attenuationColor:{value:new qt(0)},specularIntensity:{value:1},specularIntensityMap:{value:null},specularColor:{value:new qt(1,1,1)},specularColorMap:{value:null}}]),vertexShader:bn.meshphysical_vert,fragmentShader:bn.meshphysical_frag};const Tn={r:0,b:0,g:0};function An(t,e,i,n,r,s,a){const o=new qt(0);let c,h,u=!0===s?0:1,d=null,p=0,m=null;function f(e,i){e.getRGB(Tn,nn(t)),n.buffers.color.setClear(Tn.r,Tn.g,Tn.b,i,a)}return{getClearColor:function(){return o},setClearColor:function(t,e=1){o.set(t),u=e,f(o,u)},getClearAlpha:function(){return u},setClearAlpha:function(t){u=t,f(o,u)},render:function(n,s){let a=!1,g=!0===s.isScene?s.background:null;if(g&&g.isTexture){g=(s.backgroundBlurriness>0?i:e).get(g)}const v=t.xr,x=v.getSession&&v.getSession();x&&"additive"===x.environmentBlendMode&&(g=null),null===g?f(o,u):g&&g.isColor&&(f(g,1),a=!0),(t.autoClear||a)&&t.clear(t.autoClearColor,t.autoClearDepth,t.autoClearStencil),g&&(g.isCubeTexture||g.mapping===l)?(void 0===h&&(h=new Ki(new Qi(1,1,1),new sn({name:"BackgroundCubeMaterial",uniforms:tn(Sn.backgroundCube.uniforms),vertexShader:Sn.backgroundCube.vertexShader,fragmentShader:Sn.backgroundCube.fragmentShader,side:1,depthTest:!1,depthWrite:!1,fog:!1})),h.geometry.deleteAttribute("normal"),h.geometry.deleteAttribute("uv"),h.onBeforeRender=function(t,e,i){this.matrixWorld.copyPosition(i.matrixWorld)},Object.defineProperty(h.material,"envMap",{get:function(){return this.uniforms.envMap.value}}),r.update(h)),h.material.uniforms.envMap.value=g,h.material.uniforms.flipEnvMap.value=g.isCubeTexture&&!1===g.isRenderTargetTexture?-1:1,h.material.uniforms.backgroundBlurriness.value=s.backgroundBlurriness,h.material.uniforms.backgroundIntensity.value=s.backgroundIntensity,d===g&&p===g.version&&m===t.toneMapping||(h.material.needsUpdate=!0,d=g,p=g.version,m=t.toneMapping),h.layers.enableAll(),n.unshift(h,h.geometry,h.material,0,0,null)):g&&g.isTexture&&(void 0===c&&(c=new Ki(new Mn(2,2),new sn({name:"BackgroundMaterial",uniforms:tn(Sn.background.uniforms),vertexShader:Sn.background.vertexShader,fragmentShader:Sn.background.fragmentShader,side:0,depthTest:!1,depthWrite:!1,fog:!1})),c.geometry.deleteAttribute("normal"),Object.defineProperty(c.material,"map",{get:function(){return this.uniforms.t2D.value}}),r.update(c)),c.material.uniforms.t2D.value=g,c.material.uniforms.backgroundIntensity.value=s.backgroundIntensity,!0===g.matrixAutoUpdate&&g.updateMatrix(),c.material.uniforms.uvTransform.value.copy(g.matrix),d===g&&p===g.version&&m===t.toneMapping||(c.material.needsUpdate=!0,d=g,p=g.version,m=t.toneMapping),c.layers.enableAll(),n.unshift(c,c.geometry,c.material,0,0,null))}}}function En(t,e,i,n){const r=t.getParameter(34921),s=n.isWebGL2?null:e.get("OES_vertex_array_object"),a=n.isWebGL2||null!==s,o={},l=p(null);let c=l,h=!1;function u(e){return n.isWebGL2?t.bindVertexArray(e):s.bindVertexArrayOES(e)}function d(e){return n.isWebGL2?t.deleteVertexArray(e):s.deleteVertexArrayOES(e)}function p(t){const e=[],i=[],n=[];for(let t=0;t=0){const i=r[e];let n=s[e];if(void 0===n&&("instanceMatrix"===e&&t.instanceMatrix&&(n=t.instanceMatrix),"instanceColor"===e&&t.instanceColor&&(n=t.instanceColor)),void 0===i)return!0;if(i.attribute!==n)return!0;if(n&&i.data!==n.data)return!0;a++}}return c.attributesNum!==a||c.index!==n}(r,_,d,y),M&&function(t,e,i,n){const r={},s=e.attributes;let a=0;const o=i.getAttributes();for(const e in o){if(o[e].location>=0){let i=s[e];void 0===i&&("instanceMatrix"===e&&t.instanceMatrix&&(i=t.instanceMatrix),"instanceColor"===e&&t.instanceColor&&(i=t.instanceColor));const n={};n.attribute=i,i&&i.data&&(n.data=i.data),r[e]=n,a++}}c.attributes=r,c.attributesNum=a,c.index=n}(r,_,d,y)}else{const t=!0===l.wireframe;c.geometry===_.id&&c.program===d.id&&c.wireframe===t||(c.geometry=_.id,c.program=d.id,c.wireframe=t,M=!0)}null!==y&&i.update(y,34963),(M||h)&&(h=!1,function(r,s,a,o){if(!1===n.isWebGL2&&(r.isInstancedMesh||o.isInstancedBufferGeometry)&&null===e.get("ANGLE_instanced_arrays"))return;m();const l=o.attributes,c=a.getAttributes(),h=s.defaultAttributeValues;for(const e in c){const n=c[e];if(n.location>=0){let s=l[e];if(void 0===s&&("instanceMatrix"===e&&r.instanceMatrix&&(s=r.instanceMatrix),"instanceColor"===e&&r.instanceColor&&(s=r.instanceColor)),void 0!==s){const e=s.normalized,a=s.itemSize,l=i.get(s);if(void 0===l)continue;const c=l.buffer,h=l.type,u=l.bytesPerElement;if(s.isInterleavedBufferAttribute){const i=s.data,l=i.stride,d=s.offset;if(i.isInstancedInterleavedBuffer){for(let t=0;t0&&t.getShaderPrecisionFormat(35632,36338).precision>0)return"highp";e="mediump"}return"mediump"===e&&t.getShaderPrecisionFormat(35633,36337).precision>0&&t.getShaderPrecisionFormat(35632,36337).precision>0?"mediump":"lowp"}const s="undefined"!=typeof WebGL2RenderingContext&&t instanceof WebGL2RenderingContext||"undefined"!=typeof WebGL2ComputeRenderingContext&&t instanceof WebGL2ComputeRenderingContext;let a=void 0!==i.precision?i.precision:"highp";const o=r(a);o!==a&&(console.warn("THREE.WebGLRenderer:",a,"not supported, using",o,"instead."),a=o);const l=s||e.has("WEBGL_draw_buffers"),c=!0===i.logarithmicDepthBuffer,h=t.getParameter(34930),u=t.getParameter(35660),d=t.getParameter(3379),p=t.getParameter(34076),m=t.getParameter(34921),f=t.getParameter(36347),g=t.getParameter(36348),v=t.getParameter(36349),x=u>0,_=s||e.has("OES_texture_float");return{isWebGL2:s,drawBuffers:l,getMaxAnisotropy:function(){if(void 0!==n)return n;if(!0===e.has("EXT_texture_filter_anisotropic")){const i=e.get("EXT_texture_filter_anisotropic");n=t.getParameter(i.MAX_TEXTURE_MAX_ANISOTROPY_EXT)}else n=0;return n},getMaxPrecision:r,precision:a,logarithmicDepthBuffer:c,maxTextures:h,maxVertexTextures:u,maxTextureSize:d,maxCubemapSize:p,maxAttributes:m,maxVertexUniforms:f,maxVaryings:g,maxFragmentUniforms:v,vertexTextures:x,floatFragmentTextures:_,floatVertexTextures:x&&_,maxSamples:s?t.getParameter(36183):0}}function Rn(t){const e=this;let i=null,n=0,r=!1,s=!1;const a=new fn,o=new Rt,l={value:null,needsUpdate:!1};function c(){l.value!==i&&(l.value=i,l.needsUpdate=n>0),e.numPlanes=n,e.numIntersection=0}function h(t,i,n,r){const s=null!==t?t.length:0;let c=null;if(0!==s){if(c=l.value,!0!==r||null===c){const e=n+4*s,r=i.matrixWorldInverse;o.getNormalMatrix(r),(null===c||c.length0){const a=new un(s.height/2);return a.fromEquirectangularTexture(t,r),e.set(r,a),r.addEventListener("dispose",n),i(a.texture,r.mapping)}return null}}}return r},dispose:function(){e=new WeakMap}}}class In extends an{constructor(t=-1,e=1,i=1,n=-1,r=.1,s=2e3){super(),this.isOrthographicCamera=!0,this.type="OrthographicCamera",this.zoom=1,this.view=null,this.left=t,this.right=e,this.top=i,this.bottom=n,this.near=r,this.far=s,this.updateProjectionMatrix()}copy(t,e){return super.copy(t,e),this.left=t.left,this.right=t.right,this.top=t.top,this.bottom=t.bottom,this.near=t.near,this.far=t.far,this.zoom=t.zoom,this.view=null===t.view?null:Object.assign({},t.view),this}setViewOffset(t,e,i,n,r,s){null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=i,this.view.offsetY=n,this.view.width=r,this.view.height=s,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const t=(this.right-this.left)/(2*this.zoom),e=(this.top-this.bottom)/(2*this.zoom),i=(this.right+this.left)/2,n=(this.top+this.bottom)/2;let r=i-t,s=i+t,a=n+e,o=n-e;if(null!==this.view&&this.view.enabled){const t=(this.right-this.left)/this.view.fullWidth/this.zoom,e=(this.top-this.bottom)/this.view.fullHeight/this.zoom;r+=t*this.view.offsetX,s=r+t*this.view.width,a-=e*this.view.offsetY,o=a-e*this.view.height}this.projectionMatrix.makeOrthographic(r,s,a,o,this.near,this.far),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(t){const e=super.toJSON(t);return e.object.zoom=this.zoom,e.object.left=this.left,e.object.right=this.right,e.object.top=this.top,e.object.bottom=this.bottom,e.object.near=this.near,e.object.far=this.far,null!==this.view&&(e.object.view=Object.assign({},this.view)),e}}const Dn=[.125,.215,.35,.446,.526,.582],Nn=20,On=new In,zn=new qt;let Un=null;const Bn=(1+Math.sqrt(5))/2,Fn=1/Bn,kn=[new re(1,1,1),new re(-1,1,1),new re(1,1,-1),new re(-1,1,-1),new re(0,Bn,Fn),new re(0,Bn,-Fn),new re(Fn,0,Bn),new re(-Fn,0,Bn),new re(Bn,Fn,0),new re(-Bn,Fn,0)];class Gn{constructor(t){this._renderer=t,this._pingPongRenderTarget=null,this._lodMax=0,this._cubeSize=0,this._lodPlanes=[],this._sizeLods=[],this._sigmas=[],this._blurMaterial=null,this._cubemapMaterial=null,this._equirectMaterial=null,this._compileMaterial(this._blurMaterial)}fromScene(t,e=0,i=.1,n=100){Un=this._renderer.getRenderTarget(),this._setSize(256);const r=this._allocateTargets();return r.depthBuffer=!0,this._sceneToCubeUV(t,i,n,r),e>0&&this._blur(r,0,0,e),this._applyPMREM(r),this._cleanup(r),r}fromEquirectangular(t,e=null){return this._fromTexture(t,e)}fromCubemap(t,e=null){return this._fromTexture(t,e)}compileCubemapShader(){null===this._cubemapMaterial&&(this._cubemapMaterial=jn(),this._compileMaterial(this._cubemapMaterial))}compileEquirectangularShader(){null===this._equirectMaterial&&(this._equirectMaterial=Wn(),this._compileMaterial(this._equirectMaterial))}dispose(){this._dispose(),null!==this._cubemapMaterial&&this._cubemapMaterial.dispose(),null!==this._equirectMaterial&&this._equirectMaterial.dispose()}_setSize(t){this._lodMax=Math.floor(Math.log2(t)),this._cubeSize=Math.pow(2,this._lodMax)}_dispose(){null!==this._blurMaterial&&this._blurMaterial.dispose(),null!==this._pingPongRenderTarget&&this._pingPongRenderTarget.dispose();for(let t=0;tt-4?o=Dn[a-t+4-1]:0===a&&(o=0),n.push(o);const l=1/(s-2),c=-l,h=1+l,u=[c,c,h,c,h,h,c,c,h,h,c,h],d=6,p=6,m=3,f=2,g=1,v=new Float32Array(m*p*d),x=new Float32Array(f*p*d),_=new Float32Array(g*p*d);for(let t=0;t2?0:-1,n=[e,i,0,e+2/3,i,0,e+2/3,i+1,0,e,i,0,e+2/3,i+1,0,e,i+1,0];v.set(n,m*p*t),x.set(u,f*p*t);const r=[t,t,t,t,t,t];_.set(r,g*p*t)}const y=new Di;y.setAttribute("position",new bi(v,m)),y.setAttribute("uv",new bi(x,f)),y.setAttribute("faceIndex",new bi(_,g)),e.push(y),r>4&&r--}return{lodPlanes:e,sizeLods:i,sigmas:n}}(n)),this._blurMaterial=function(t,e,i){const n=new Float32Array(Nn),r=new re(0,1,0);return new sn({name:"SphericalGaussianBlur",defines:{n:Nn,CUBEUV_TEXEL_WIDTH:1/e,CUBEUV_TEXEL_HEIGHT:1/i,CUBEUV_MAX_MIP:`${t}.0`},uniforms:{envMap:{value:null},samples:{value:1},weights:{value:n},latitudinal:{value:!1},dTheta:{value:0},mipInt:{value:0},poleAxis:{value:r}},vertexShader:qn(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\t\t\tuniform int samples;\n\t\t\tuniform float weights[ n ];\n\t\t\tuniform bool latitudinal;\n\t\t\tuniform float dTheta;\n\t\t\tuniform float mipInt;\n\t\t\tuniform vec3 poleAxis;\n\n\t\t\t#define ENVMAP_TYPE_CUBE_UV\n\t\t\t#include \n\n\t\t\tvec3 getSample( float theta, vec3 axis ) {\n\n\t\t\t\tfloat cosTheta = cos( theta );\n\t\t\t\t// Rodrigues' axis-angle rotation\n\t\t\t\tvec3 sampleDirection = vOutputDirection * cosTheta\n\t\t\t\t\t+ cross( axis, vOutputDirection ) * sin( theta )\n\t\t\t\t\t+ axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta );\n\n\t\t\t\treturn bilinearCubeUV( envMap, sampleDirection, mipInt );\n\n\t\t\t}\n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection );\n\n\t\t\t\tif ( all( equal( axis, vec3( 0.0 ) ) ) ) {\n\n\t\t\t\t\taxis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x );\n\n\t\t\t\t}\n\n\t\t\t\taxis = normalize( axis );\n\n\t\t\t\tgl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t\t\t\tgl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis );\n\n\t\t\t\tfor ( int i = 1; i < n; i++ ) {\n\n\t\t\t\t\tif ( i >= samples ) {\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tfloat theta = dTheta * float( i );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( theta, axis );\n\n\t\t\t\t}\n\n\t\t\t}\n\t\t",blending:0,depthTest:!1,depthWrite:!1})}(n,t,e)}return n}_compileMaterial(t){const e=new Ki(this._lodPlanes[0],t);this._renderer.compile(e,On)}_sceneToCubeUV(t,e,i,n){const r=new on(90,1,e,i),s=[1,-1,1,1,1,1],a=[1,1,1,-1,-1,-1],o=this._renderer,l=o.autoClear,c=o.toneMapping;o.getClearColor(zn),o.toneMapping=0,o.autoClear=!1;const h=new _i({name:"PMREM.Background",side:1,depthWrite:!1,depthTest:!1}),u=new Ki(new Qi,h);let d=!1;const p=t.background;p?p.isColor&&(h.color.copy(p),t.background=null,d=!0):(h.color.copy(zn),d=!0);for(let e=0;e<6;e++){const i=e%3;0===i?(r.up.set(0,s[e],0),r.lookAt(a[e],0,0)):1===i?(r.up.set(0,0,s[e]),r.lookAt(0,a[e],0)):(r.up.set(0,s[e],0),r.lookAt(0,0,a[e]));const l=this._cubeSize;Hn(n,i*l,e>2?l:0,l,l),o.setRenderTarget(n),d&&o.render(u,r),o.render(t,r)}u.geometry.dispose(),u.material.dispose(),o.toneMapping=c,o.autoClear=l,t.background=p}_textureToCubeUV(t,e){const i=this._renderer,n=t.mapping===r||t.mapping===s;n?(null===this._cubemapMaterial&&(this._cubemapMaterial=jn()),this._cubemapMaterial.uniforms.flipEnvMap.value=!1===t.isRenderTargetTexture?-1:1):null===this._equirectMaterial&&(this._equirectMaterial=Wn());const a=n?this._cubemapMaterial:this._equirectMaterial,o=new Ki(this._lodPlanes[0],a);a.uniforms.envMap.value=t;const l=this._cubeSize;Hn(e,0,0,3*l,2*l),i.setRenderTarget(e),i.render(o,On)}_applyPMREM(t){const e=this._renderer,i=e.autoClear;e.autoClear=!1;for(let e=1;eNn&&console.warn(`sigmaRadians, ${r}, is too large and will clip, as it requested ${m} samples when the maximum is set to 20`);const f=[];let g=0;for(let t=0;tv-4?n-v+4:0),4*(this._cubeSize-x),3*x,2*x),o.setRenderTarget(e),o.render(c,On)}}function Vn(t,e,i){const n=new te(t,e,i);return n.texture.mapping=l,n.texture.name="PMREM.cubeUv",n.scissorTest=!0,n}function Hn(t,e,i,n,r){t.viewport.set(e,i,n,r),t.scissor.set(e,i,n,r)}function Wn(){return new sn({name:"EquirectangularToCubeUV",uniforms:{envMap:{value:null}},vertexShader:qn(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\n\t\t\t#include \n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 outputDirection = normalize( vOutputDirection );\n\t\t\t\tvec2 uv = equirectUv( outputDirection );\n\n\t\t\t\tgl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 );\n\n\t\t\t}\n\t\t",blending:0,depthTest:!1,depthWrite:!1})}function jn(){return new sn({name:"CubemapToCubeUV",uniforms:{envMap:{value:null},flipEnvMap:{value:-1}},vertexShader:qn(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tuniform float flipEnvMap;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform samplerCube envMap;\n\n\t\t\tvoid main() {\n\n\t\t\t\tgl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) );\n\n\t\t\t}\n\t\t",blending:0,depthTest:!1,depthWrite:!1})}function qn(){return"\n\n\t\tprecision mediump float;\n\t\tprecision mediump int;\n\n\t\tattribute float faceIndex;\n\n\t\tvarying vec3 vOutputDirection;\n\n\t\t// RH coordinate system; PMREM face-indexing convention\n\t\tvec3 getDirection( vec2 uv, float face ) {\n\n\t\t\tuv = 2.0 * uv - 1.0;\n\n\t\t\tvec3 direction = vec3( uv, 1.0 );\n\n\t\t\tif ( face == 0.0 ) {\n\n\t\t\t\tdirection = direction.zyx; // ( 1, v, u ) pos x\n\n\t\t\t} else if ( face == 1.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xz *= -1.0; // ( -u, 1, -v ) pos y\n\n\t\t\t} else if ( face == 2.0 ) {\n\n\t\t\t\tdirection.x *= -1.0; // ( -u, v, 1 ) pos z\n\n\t\t\t} else if ( face == 3.0 ) {\n\n\t\t\t\tdirection = direction.zyx;\n\t\t\t\tdirection.xz *= -1.0; // ( -1, v, -u ) neg x\n\n\t\t\t} else if ( face == 4.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xy *= -1.0; // ( -u, -1, v ) neg y\n\n\t\t\t} else if ( face == 5.0 ) {\n\n\t\t\t\tdirection.z *= -1.0; // ( u, v, -1 ) neg z\n\n\t\t\t}\n\n\t\t\treturn direction;\n\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tvOutputDirection = getDirection( uv, faceIndex );\n\t\t\tgl_Position = vec4( position, 1.0 );\n\n\t\t}\n\t"}function Xn(t){let e=new WeakMap,i=null;function n(t){const i=t.target;i.removeEventListener("dispose",n);const r=e.get(i);void 0!==r&&(e.delete(i),r.dispose())}return{get:function(l){if(l&&l.isTexture){const c=l.mapping,h=c===a||c===o,u=c===r||c===s;if(h||u){if(l.isRenderTargetTexture&&!0===l.needsPMREMUpdate){l.needsPMREMUpdate=!1;let n=e.get(l);return null===i&&(i=new Gn(t)),n=h?i.fromEquirectangular(l,n):i.fromCubemap(l,n),e.set(l,n),n.texture}if(e.has(l))return e.get(l).texture;{const r=l.image;if(h&&r&&r.height>0||u&&r&&function(t){let e=0;const i=6;for(let n=0;ne.maxTextureSize&&(E=Math.ceil(A/e.maxTextureSize),A=e.maxTextureSize);const C=new Float32Array(A*E*4*m),L=new ee(C,A,E,m);L.type=M,L.needsUpdate=!0;const R=4*T;for(let I=0;I0)return t;const r=e*i;let s=ar[r];if(void 0===s&&(s=new Float32Array(r),ar[r]=s),0!==e){n.toArray(s,0);for(let n=1,r=0;n!==e;++n)r+=i,t[n].toArray(s,r)}return s}function dr(t,e){if(t.length!==e.length)return!1;for(let i=0,n=t.length;i":" "} ${r}: ${i[t]}`)}return n.join("\n")}(t.getShaderSource(e),n)}return r}function cs(t,e){const i=function(t){switch(t){case at:return["Linear","( value )"];case ot:return["sRGB","( value )"];default:return console.warn("THREE.WebGLProgram: Unsupported encoding:",t),["Linear","( value )"]}}(e);return"vec4 "+t+"( vec4 value ) { return LinearTo"+i[0]+i[1]+"; }"}function hs(t,e){let i;switch(e){case 1:i="Linear";break;case 2:i="Reinhard";break;case 3:i="OptimizedCineon";break;case 4:i="ACESFilmic";break;case 5:i="Custom";break;default:console.warn("THREE.WebGLProgram: Unsupported toneMapping:",e),i="Linear"}return"vec3 "+t+"( vec3 color ) { return "+i+"ToneMapping( color ); }"}function us(t){return""!==t}function ds(t,e){const i=e.numSpotLightShadows+e.numSpotLightMaps-e.numSpotLightShadowsWithMaps;return t.replace(/NUM_DIR_LIGHTS/g,e.numDirLights).replace(/NUM_SPOT_LIGHTS/g,e.numSpotLights).replace(/NUM_SPOT_LIGHT_MAPS/g,e.numSpotLightMaps).replace(/NUM_SPOT_LIGHT_COORDS/g,i).replace(/NUM_RECT_AREA_LIGHTS/g,e.numRectAreaLights).replace(/NUM_POINT_LIGHTS/g,e.numPointLights).replace(/NUM_HEMI_LIGHTS/g,e.numHemiLights).replace(/NUM_DIR_LIGHT_SHADOWS/g,e.numDirLightShadows).replace(/NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS/g,e.numSpotLightShadowsWithMaps).replace(/NUM_SPOT_LIGHT_SHADOWS/g,e.numSpotLightShadows).replace(/NUM_POINT_LIGHT_SHADOWS/g,e.numPointLightShadows)}function ps(t,e){return t.replace(/NUM_CLIPPING_PLANES/g,e.numClippingPlanes).replace(/UNION_CLIPPING_PLANES/g,e.numClippingPlanes-e.numClipIntersection)}const ms=/^[ \t]*#include +<([\w\d./]+)>/gm;function fs(t){return t.replace(ms,gs)}function gs(t,e){const i=bn[e];if(void 0===i)throw new Error("Can not resolve #include <"+e+">");return fs(i)}const vs=/#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*<\s*(\d+)\s*;\s*i\s*\+\+\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g;function xs(t){return t.replace(vs,_s)}function _s(t,e,i,n){let r="";for(let t=parseInt(e);t0&&(_+="\n"),y=[g,v].filter(us).join("\n"),y.length>0&&(y+="\n")):(_=[ys(i),"#define SHADER_NAME "+i.shaderName,v,i.instancing?"#define USE_INSTANCING":"",i.instancingColor?"#define USE_INSTANCING_COLOR":"",i.supportsVertexTextures?"#define VERTEX_TEXTURES":"",i.useFog&&i.fog?"#define USE_FOG":"",i.useFog&&i.fogExp2?"#define FOG_EXP2":"",i.map?"#define USE_MAP":"",i.envMap?"#define USE_ENVMAP":"",i.envMap?"#define "+p:"",i.lightMap?"#define USE_LIGHTMAP":"",i.aoMap?"#define USE_AOMAP":"",i.emissiveMap?"#define USE_EMISSIVEMAP":"",i.bumpMap?"#define USE_BUMPMAP":"",i.normalMap?"#define USE_NORMALMAP":"",i.normalMap&&i.objectSpaceNormalMap?"#define OBJECTSPACE_NORMALMAP":"",i.normalMap&&i.tangentSpaceNormalMap?"#define TANGENTSPACE_NORMALMAP":"",i.clearcoatMap?"#define USE_CLEARCOATMAP":"",i.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",i.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",i.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",i.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",i.displacementMap&&i.supportsVertexTextures?"#define USE_DISPLACEMENTMAP":"",i.specularMap?"#define USE_SPECULARMAP":"",i.specularIntensityMap?"#define USE_SPECULARINTENSITYMAP":"",i.specularColorMap?"#define USE_SPECULARCOLORMAP":"",i.roughnessMap?"#define USE_ROUGHNESSMAP":"",i.metalnessMap?"#define USE_METALNESSMAP":"",i.alphaMap?"#define USE_ALPHAMAP":"",i.transmission?"#define USE_TRANSMISSION":"",i.transmissionMap?"#define USE_TRANSMISSIONMAP":"",i.thicknessMap?"#define USE_THICKNESSMAP":"",i.sheenColorMap?"#define USE_SHEENCOLORMAP":"",i.sheenRoughnessMap?"#define USE_SHEENROUGHNESSMAP":"",i.vertexTangents?"#define USE_TANGENT":"",i.vertexColors?"#define USE_COLOR":"",i.vertexAlphas?"#define USE_COLOR_ALPHA":"",i.vertexUvs?"#define USE_UV":"",i.uvsVertexOnly?"#define UVS_VERTEX_ONLY":"",i.flatShading?"#define FLAT_SHADED":"",i.skinning?"#define USE_SKINNING":"",i.morphTargets?"#define USE_MORPHTARGETS":"",i.morphNormals&&!1===i.flatShading?"#define USE_MORPHNORMALS":"",i.morphColors&&i.isWebGL2?"#define USE_MORPHCOLORS":"",i.morphTargetsCount>0&&i.isWebGL2?"#define MORPHTARGETS_TEXTURE":"",i.morphTargetsCount>0&&i.isWebGL2?"#define MORPHTARGETS_TEXTURE_STRIDE "+i.morphTextureStride:"",i.morphTargetsCount>0&&i.isWebGL2?"#define MORPHTARGETS_COUNT "+i.morphTargetsCount:"",i.doubleSided?"#define DOUBLE_SIDED":"",i.flipSided?"#define FLIP_SIDED":"",i.shadowMapEnabled?"#define USE_SHADOWMAP":"",i.shadowMapEnabled?"#define "+u:"",i.sizeAttenuation?"#define USE_SIZEATTENUATION":"",i.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",i.logarithmicDepthBuffer&&i.rendererExtensionFragDepth?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;","#ifdef USE_INSTANCING","\tattribute mat4 instanceMatrix;","#endif","#ifdef USE_INSTANCING_COLOR","\tattribute vec3 instanceColor;","#endif","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_TANGENT","\tattribute vec4 tangent;","#endif","#if defined( USE_COLOR_ALPHA )","\tattribute vec4 color;","#elif defined( USE_COLOR )","\tattribute vec3 color;","#endif","#if ( defined( USE_MORPHTARGETS ) && ! defined( MORPHTARGETS_TEXTURE ) )","\tattribute vec3 morphTarget0;","\tattribute vec3 morphTarget1;","\tattribute vec3 morphTarget2;","\tattribute vec3 morphTarget3;","\t#ifdef USE_MORPHNORMALS","\t\tattribute vec3 morphNormal0;","\t\tattribute vec3 morphNormal1;","\t\tattribute vec3 morphNormal2;","\t\tattribute vec3 morphNormal3;","\t#else","\t\tattribute vec3 morphTarget4;","\t\tattribute vec3 morphTarget5;","\t\tattribute vec3 morphTarget6;","\t\tattribute vec3 morphTarget7;","\t#endif","#endif","#ifdef USE_SKINNING","\tattribute vec4 skinIndex;","\tattribute vec4 skinWeight;","#endif","\n"].filter(us).join("\n"),y=[g,ys(i),"#define SHADER_NAME "+i.shaderName,v,i.useFog&&i.fog?"#define USE_FOG":"",i.useFog&&i.fogExp2?"#define FOG_EXP2":"",i.map?"#define USE_MAP":"",i.matcap?"#define USE_MATCAP":"",i.envMap?"#define USE_ENVMAP":"",i.envMap?"#define "+d:"",i.envMap?"#define "+p:"",i.envMap?"#define "+m:"",f?"#define CUBEUV_TEXEL_WIDTH "+f.texelWidth:"",f?"#define CUBEUV_TEXEL_HEIGHT "+f.texelHeight:"",f?"#define CUBEUV_MAX_MIP "+f.maxMip+".0":"",i.lightMap?"#define USE_LIGHTMAP":"",i.aoMap?"#define USE_AOMAP":"",i.emissiveMap?"#define USE_EMISSIVEMAP":"",i.bumpMap?"#define USE_BUMPMAP":"",i.normalMap?"#define USE_NORMALMAP":"",i.normalMap&&i.objectSpaceNormalMap?"#define OBJECTSPACE_NORMALMAP":"",i.normalMap&&i.tangentSpaceNormalMap?"#define TANGENTSPACE_NORMALMAP":"",i.clearcoat?"#define USE_CLEARCOAT":"",i.clearcoatMap?"#define USE_CLEARCOATMAP":"",i.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",i.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",i.iridescence?"#define USE_IRIDESCENCE":"",i.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",i.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",i.specularMap?"#define USE_SPECULARMAP":"",i.specularIntensityMap?"#define USE_SPECULARINTENSITYMAP":"",i.specularColorMap?"#define USE_SPECULARCOLORMAP":"",i.roughnessMap?"#define USE_ROUGHNESSMAP":"",i.metalnessMap?"#define USE_METALNESSMAP":"",i.alphaMap?"#define USE_ALPHAMAP":"",i.alphaTest?"#define USE_ALPHATEST":"",i.sheen?"#define USE_SHEEN":"",i.sheenColorMap?"#define USE_SHEENCOLORMAP":"",i.sheenRoughnessMap?"#define USE_SHEENROUGHNESSMAP":"",i.transmission?"#define USE_TRANSMISSION":"",i.transmissionMap?"#define USE_TRANSMISSIONMAP":"",i.thicknessMap?"#define USE_THICKNESSMAP":"",i.decodeVideoTexture?"#define DECODE_VIDEO_TEXTURE":"",i.vertexTangents?"#define USE_TANGENT":"",i.vertexColors||i.instancingColor?"#define USE_COLOR":"",i.vertexAlphas?"#define USE_COLOR_ALPHA":"",i.vertexUvs?"#define USE_UV":"",i.uvsVertexOnly?"#define UVS_VERTEX_ONLY":"",i.gradientMap?"#define USE_GRADIENTMAP":"",i.flatShading?"#define FLAT_SHADED":"",i.doubleSided?"#define DOUBLE_SIDED":"",i.flipSided?"#define FLIP_SIDED":"",i.shadowMapEnabled?"#define USE_SHADOWMAP":"",i.shadowMapEnabled?"#define "+u:"",i.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",i.physicallyCorrectLights?"#define PHYSICALLY_CORRECT_LIGHTS":"",i.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",i.logarithmicDepthBuffer&&i.rendererExtensionFragDepth?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;",0!==i.toneMapping?"#define TONE_MAPPING":"",0!==i.toneMapping?bn.tonemapping_pars_fragment:"",0!==i.toneMapping?hs("toneMapping",i.toneMapping):"",i.dithering?"#define DITHERING":"",i.opaque?"#define OPAQUE":"",bn.encodings_pars_fragment,cs("linearToOutputTexel",i.outputEncoding),i.useDepthPacking?"#define DEPTH_PACKING "+i.depthPacking:"","\n"].filter(us).join("\n")),c=fs(c),c=ds(c,i),c=ps(c,i),h=fs(h),h=ds(h,i),h=ps(h,i),c=xs(c),h=xs(h),i.isWebGL2&&!0!==i.isRawShaderMaterial&&(M="#version 300 es\n",_=["precision mediump sampler2DArray;","#define attribute in","#define varying out","#define texture2D texture"].join("\n")+"\n"+_,y=["#define varying in",i.glslVersion===dt?"":"layout(location = 0) out highp vec4 pc_fragColor;",i.glslVersion===dt?"":"#define gl_FragColor pc_fragColor","#define gl_FragDepthEXT gl_FragDepth","#define texture2D texture","#define textureCube texture","#define texture2DProj textureProj","#define texture2DLodEXT textureLod","#define texture2DProjLodEXT textureProjLod","#define textureCubeLodEXT textureLod","#define texture2DGradEXT textureGrad","#define texture2DProjGradEXT textureProjGrad","#define textureCubeGradEXT textureGrad"].join("\n")+"\n"+y);const b=M+y+h,w=as(a,35633,M+_+c),S=as(a,35632,b);if(a.attachShader(x,w),a.attachShader(x,S),void 0!==i.index0AttributeName?a.bindAttribLocation(x,0,i.index0AttributeName):!0===i.morphTargets&&a.bindAttribLocation(x,0,"position"),a.linkProgram(x),t.debug.checkShaderErrors){const t=a.getProgramInfoLog(x).trim(),e=a.getShaderInfoLog(w).trim(),i=a.getShaderInfoLog(S).trim();let n=!0,r=!0;if(!1===a.getProgramParameter(x,35714)){n=!1;const e=ls(a,w,"vertex"),i=ls(a,S,"fragment");console.error("THREE.WebGLProgram: Shader Error "+a.getError()+" - VALIDATE_STATUS "+a.getProgramParameter(x,35715)+"\n\nProgram Info Log: "+t+"\n"+e+"\n"+i)}else""!==t?console.warn("THREE.WebGLProgram: Program Info Log:",t):""!==e&&""!==i||(r=!1);r&&(this.diagnostics={runnable:n,programLog:t,vertexShader:{log:e,prefix:_},fragmentShader:{log:i,prefix:y}})}let T,A;return a.deleteShader(w),a.deleteShader(S),this.getUniforms=function(){return void 0===T&&(T=new ss(a,x)),T},this.getAttributes=function(){return void 0===A&&(A=function(t,e){const i={},n=t.getProgramParameter(e,35721);for(let r=0;r0,D=s.clearcoat>0,N=s.iridescence>0;return{isWebGL2:u,shaderID:w,shaderName:s.type,vertexShader:A,fragmentShader:E,defines:s.defines,customVertexShaderID:C,customFragmentShaderID:L,isRawShaderMaterial:!0===s.isRawShaderMaterial,glslVersion:s.glslVersion,precision:m,instancing:!0===v.isInstancedMesh,instancingColor:!0===v.isInstancedMesh&&null!==v.instanceColor,supportsVertexTextures:p,outputEncoding:null===P?t.outputEncoding:!0===P.isXRRenderTarget?P.texture.encoding:at,map:!!s.map,matcap:!!s.matcap,envMap:!!M,envMapMode:M&&M.mapping,envMapCubeUVHeight:b,lightMap:!!s.lightMap,aoMap:!!s.aoMap,emissiveMap:!!s.emissiveMap,bumpMap:!!s.bumpMap,normalMap:!!s.normalMap,objectSpaceNormalMap:1===s.normalMapType,tangentSpaceNormalMap:0===s.normalMapType,decodeVideoTexture:!!s.map&&!0===s.map.isVideoTexture&&s.map.encoding===ot,clearcoat:D,clearcoatMap:D&&!!s.clearcoatMap,clearcoatRoughnessMap:D&&!!s.clearcoatRoughnessMap,clearcoatNormalMap:D&&!!s.clearcoatNormalMap,iridescence:N,iridescenceMap:N&&!!s.iridescenceMap,iridescenceThicknessMap:N&&!!s.iridescenceThicknessMap,displacementMap:!!s.displacementMap,roughnessMap:!!s.roughnessMap,metalnessMap:!!s.metalnessMap,specularMap:!!s.specularMap,specularIntensityMap:!!s.specularIntensityMap,specularColorMap:!!s.specularColorMap,opaque:!1===s.transparent&&1===s.blending,alphaMap:!!s.alphaMap,alphaTest:I,gradientMap:!!s.gradientMap,sheen:s.sheen>0,sheenColorMap:!!s.sheenColorMap,sheenRoughnessMap:!!s.sheenRoughnessMap,transmission:s.transmission>0,transmissionMap:!!s.transmissionMap,thicknessMap:!!s.thicknessMap,combine:s.combine,vertexTangents:!!s.normalMap&&!!_.attributes.tangent,vertexColors:s.vertexColors,vertexAlphas:!0===s.vertexColors&&!!_.attributes.color&&4===_.attributes.color.itemSize,vertexUvs:!!(s.map||s.bumpMap||s.normalMap||s.specularMap||s.alphaMap||s.emissiveMap||s.roughnessMap||s.metalnessMap||s.clearcoatMap||s.clearcoatRoughnessMap||s.clearcoatNormalMap||s.iridescenceMap||s.iridescenceThicknessMap||s.displacementMap||s.transmissionMap||s.thicknessMap||s.specularIntensityMap||s.specularColorMap||s.sheenColorMap||s.sheenRoughnessMap),uvsVertexOnly:!(s.map||s.bumpMap||s.normalMap||s.specularMap||s.alphaMap||s.emissiveMap||s.roughnessMap||s.metalnessMap||s.clearcoatNormalMap||s.iridescenceMap||s.iridescenceThicknessMap||s.transmission>0||s.transmissionMap||s.thicknessMap||s.specularIntensityMap||s.specularColorMap||s.sheen>0||s.sheenColorMap||s.sheenRoughnessMap||!s.displacementMap),fog:!!x,useFog:!0===s.fog,fogExp2:x&&x.isFogExp2,flatShading:!!s.flatShading,sizeAttenuation:s.sizeAttenuation,logarithmicDepthBuffer:d,skinning:!0===v.isSkinnedMesh,morphTargets:void 0!==_.morphAttributes.position,morphNormals:void 0!==_.morphAttributes.normal,morphColors:void 0!==_.morphAttributes.color,morphTargetsCount:T,morphTextureStride:R,numDirLights:o.directional.length,numPointLights:o.point.length,numSpotLights:o.spot.length,numSpotLightMaps:o.spotLightMap.length,numRectAreaLights:o.rectArea.length,numHemiLights:o.hemi.length,numDirLightShadows:o.directionalShadowMap.length,numPointLightShadows:o.pointShadowMap.length,numSpotLightShadows:o.spotShadowMap.length,numSpotLightShadowsWithMaps:o.numSpotLightShadowsWithMaps,numClippingPlanes:a.numPlanes,numClipIntersection:a.numIntersection,dithering:s.dithering,shadowMapEnabled:t.shadowMap.enabled&&h.length>0,shadowMapType:t.shadowMap.type,toneMapping:s.toneMapped?t.toneMapping:0,physicallyCorrectLights:t.physicallyCorrectLights,premultipliedAlpha:s.premultipliedAlpha,doubleSided:2===s.side,flipSided:1===s.side,useDepthPacking:!!s.depthPacking,depthPacking:s.depthPacking||0,index0AttributeName:s.index0AttributeName,extensionDerivatives:s.extensions&&s.extensions.derivatives,extensionFragDepth:s.extensions&&s.extensions.fragDepth,extensionDrawBuffers:s.extensions&&s.extensions.drawBuffers,extensionShaderTextureLOD:s.extensions&&s.extensions.shaderTextureLOD,rendererExtensionFragDepth:u||n.has("EXT_frag_depth"),rendererExtensionDrawBuffers:u||n.has("WEBGL_draw_buffers"),rendererExtensionShaderTextureLod:u||n.has("EXT_shader_texture_lod"),customProgramCacheKey:s.customProgramCacheKey()}},getProgramCacheKey:function(e){const i=[];if(e.shaderID?i.push(e.shaderID):(i.push(e.customVertexShaderID),i.push(e.customFragmentShaderID)),void 0!==e.defines)for(const t in e.defines)i.push(t),i.push(e.defines[t]);return!1===e.isRawShaderMaterial&&(!function(t,e){t.push(e.precision),t.push(e.outputEncoding),t.push(e.envMapMode),t.push(e.envMapCubeUVHeight),t.push(e.combine),t.push(e.vertexUvs),t.push(e.fogExp2),t.push(e.sizeAttenuation),t.push(e.morphTargetsCount),t.push(e.morphAttributeCount),t.push(e.numDirLights),t.push(e.numPointLights),t.push(e.numSpotLights),t.push(e.numSpotLightMaps),t.push(e.numHemiLights),t.push(e.numRectAreaLights),t.push(e.numDirLightShadows),t.push(e.numPointLightShadows),t.push(e.numSpotLightShadows),t.push(e.numSpotLightShadowsWithMaps),t.push(e.shadowMapType),t.push(e.toneMapping),t.push(e.numClippingPlanes),t.push(e.numClipIntersection),t.push(e.depthPacking)}(i,e),function(t,e){o.disableAll(),e.isWebGL2&&o.enable(0);e.supportsVertexTextures&&o.enable(1);e.instancing&&o.enable(2);e.instancingColor&&o.enable(3);e.map&&o.enable(4);e.matcap&&o.enable(5);e.envMap&&o.enable(6);e.lightMap&&o.enable(7);e.aoMap&&o.enable(8);e.emissiveMap&&o.enable(9);e.bumpMap&&o.enable(10);e.normalMap&&o.enable(11);e.objectSpaceNormalMap&&o.enable(12);e.tangentSpaceNormalMap&&o.enable(13);e.clearcoat&&o.enable(14);e.clearcoatMap&&o.enable(15);e.clearcoatRoughnessMap&&o.enable(16);e.clearcoatNormalMap&&o.enable(17);e.iridescence&&o.enable(18);e.iridescenceMap&&o.enable(19);e.iridescenceThicknessMap&&o.enable(20);e.displacementMap&&o.enable(21);e.specularMap&&o.enable(22);e.roughnessMap&&o.enable(23);e.metalnessMap&&o.enable(24);e.gradientMap&&o.enable(25);e.alphaMap&&o.enable(26);e.alphaTest&&o.enable(27);e.vertexColors&&o.enable(28);e.vertexAlphas&&o.enable(29);e.vertexUvs&&o.enable(30);e.vertexTangents&&o.enable(31);e.uvsVertexOnly&&o.enable(32);t.push(o.mask),o.disableAll(),e.fog&&o.enable(0);e.useFog&&o.enable(1);e.flatShading&&o.enable(2);e.logarithmicDepthBuffer&&o.enable(3);e.skinning&&o.enable(4);e.morphTargets&&o.enable(5);e.morphNormals&&o.enable(6);e.morphColors&&o.enable(7);e.premultipliedAlpha&&o.enable(8);e.shadowMapEnabled&&o.enable(9);e.physicallyCorrectLights&&o.enable(10);e.doubleSided&&o.enable(11);e.flipSided&&o.enable(12);e.useDepthPacking&&o.enable(13);e.dithering&&o.enable(14);e.specularIntensityMap&&o.enable(15);e.specularColorMap&&o.enable(16);e.transmission&&o.enable(17);e.transmissionMap&&o.enable(18);e.thicknessMap&&o.enable(19);e.sheen&&o.enable(20);e.sheenColorMap&&o.enable(21);e.sheenRoughnessMap&&o.enable(22);e.decodeVideoTexture&&o.enable(23);e.opaque&&o.enable(24);t.push(o.mask)}(i,e),i.push(t.outputEncoding)),i.push(e.customProgramCacheKey),i.join()},getUniforms:function(t){const e=f[t.type];let i;if(e){const t=Sn[e];i=rn.clone(t.uniforms)}else i=t.uniforms;return i},acquireProgram:function(e,i){let n;for(let t=0,e=h.length;t0?n.push(h):!0===a.transparent?r.push(h):i.push(h)},unshift:function(t,e,a,o,l,c){const h=s(t,e,a,o,l,c);a.transmission>0?n.unshift(h):!0===a.transparent?r.unshift(h):i.unshift(h)},finish:function(){for(let i=e,n=t.length;i1&&i.sort(t||Es),n.length>1&&n.sort(e||Cs),r.length>1&&r.sort(e||Cs)}}}function Rs(){let t=new WeakMap;return{get:function(e,i){const n=t.get(e);let r;return void 0===n?(r=new Ls,t.set(e,[r])):i>=n.length?(r=new Ls,n.push(r)):r=n[i],r},dispose:function(){t=new WeakMap}}}function Ps(){const t={};return{get:function(e){if(void 0!==t[e.id])return t[e.id];let i;switch(e.type){case"DirectionalLight":i={direction:new re,color:new qt};break;case"SpotLight":i={position:new re,direction:new re,color:new qt,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case"PointLight":i={position:new re,color:new qt,distance:0,decay:0};break;case"HemisphereLight":i={direction:new re,skyColor:new qt,groundColor:new qt};break;case"RectAreaLight":i={color:new qt,position:new re,halfWidth:new re,halfHeight:new re}}return t[e.id]=i,i}}}let Is=0;function Ds(t,e){return(e.castShadow?2:0)-(t.castShadow?2:0)+(e.map?1:0)-(t.map?1:0)}function Ns(t,e){const i=new Ps,n=function(){const t={};return{get:function(e){if(void 0!==t[e.id])return t[e.id];let i;switch(e.type){case"DirectionalLight":case"SpotLight":i={shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new Lt};break;case"PointLight":i={shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new Lt,shadowCameraNear:1,shadowCameraFar:1e3}}return t[e.id]=i,i}}}(),r={version:0,hash:{directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,numDirectionalShadows:-1,numPointShadows:-1,numSpotShadows:-1,numSpotMaps:-1},ambient:[0,0,0],probe:[],directional:[],directionalShadow:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotLightMap:[],spotShadow:[],spotShadowMap:[],spotLightMatrix:[],rectArea:[],rectAreaLTC1:null,rectAreaLTC2:null,point:[],pointShadow:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[],numSpotLightShadowsWithMaps:0};for(let t=0;t<9;t++)r.probe.push(new re);const s=new re,a=new Ne,o=new Ne;return{setup:function(s,a){let o=0,l=0,c=0;for(let t=0;t<9;t++)r.probe[t].set(0,0,0);let h=0,u=0,d=0,p=0,m=0,f=0,g=0,v=0,x=0,_=0;s.sort(Ds);const y=!0!==a?Math.PI:1;for(let t=0,e=s.length;t0&&(e.isWebGL2||!0===t.has("OES_texture_float_linear")?(r.rectAreaLTC1=wn.LTC_FLOAT_1,r.rectAreaLTC2=wn.LTC_FLOAT_2):!0===t.has("OES_texture_half_float_linear")?(r.rectAreaLTC1=wn.LTC_HALF_1,r.rectAreaLTC2=wn.LTC_HALF_2):console.error("THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions.")),r.ambient[0]=o,r.ambient[1]=l,r.ambient[2]=c;const M=r.hash;M.directionalLength===h&&M.pointLength===u&&M.spotLength===d&&M.rectAreaLength===p&&M.hemiLength===m&&M.numDirectionalShadows===f&&M.numPointShadows===g&&M.numSpotShadows===v&&M.numSpotMaps===x||(r.directional.length=h,r.spot.length=d,r.rectArea.length=p,r.point.length=u,r.hemi.length=m,r.directionalShadow.length=f,r.directionalShadowMap.length=f,r.pointShadow.length=g,r.pointShadowMap.length=g,r.spotShadow.length=v,r.spotShadowMap.length=v,r.directionalShadowMatrix.length=f,r.pointShadowMatrix.length=g,r.spotLightMatrix.length=v+x-_,r.spotLightMap.length=x,r.numSpotLightShadowsWithMaps=_,M.directionalLength=h,M.pointLength=u,M.spotLength=d,M.rectAreaLength=p,M.hemiLength=m,M.numDirectionalShadows=f,M.numPointShadows=g,M.numSpotShadows=v,M.numSpotMaps=x,r.version=Is++)},setupView:function(t,e){let i=0,n=0,l=0,c=0,h=0;const u=e.matrixWorldInverse;for(let e=0,d=t.length;e=s.length?(a=new Os(t,e),s.push(a)):a=s[r],a},dispose:function(){i=new WeakMap}}}class Us extends xi{constructor(t){super(),this.isMeshDepthMaterial=!0,this.type="MeshDepthMaterial",this.depthPacking=3200,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.setValues(t)}copy(t){return super.copy(t),this.depthPacking=t.depthPacking,this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this}}class Bs extends xi{constructor(t){super(),this.isMeshDistanceMaterial=!0,this.type="MeshDistanceMaterial",this.referencePosition=new re,this.nearDistance=1,this.farDistance=1e3,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.setValues(t)}copy(t){return super.copy(t),this.referencePosition.copy(t.referencePosition),this.nearDistance=t.nearDistance,this.farDistance=t.farDistance,this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this}}function Fs(t,e,i){let n=new xn;const r=new Lt,s=new Lt,a=new Qt,o=new Us({depthPacking:3201}),l=new Bs,c={},h=i.maxTextureSize,u={0:1,1:0,2:2},p=new sn({defines:{VSM_SAMPLES:8},uniforms:{shadow_pass:{value:null},resolution:{value:new Lt},radius:{value:4}},vertexShader:"void main() {\n\tgl_Position = vec4( position, 1.0 );\n}",fragmentShader:"uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include \nvoid main() {\n\tconst float samples = float( VSM_SAMPLES );\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n\tfloat uvStart = samples <= 1.0 ? 0.0 : - 1.0;\n\tfor ( float i = 0.0; i < samples; i ++ ) {\n\t\tfloat uvOffset = uvStart + i * uvStride;\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean / samples;\n\tsquared_mean = squared_mean / samples;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}"}),m=p.clone();m.defines.HORIZONTAL_PASS=1;const f=new Di;f.setAttribute("position",new bi(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));const g=new Ki(f,p),v=this;function x(i,n){const s=e.update(g);p.defines.VSM_SAMPLES!==i.blurSamples&&(p.defines.VSM_SAMPLES=i.blurSamples,m.defines.VSM_SAMPLES=i.blurSamples,p.needsUpdate=!0,m.needsUpdate=!0),null===i.mapPass&&(i.mapPass=new te(r.x,r.y)),p.uniforms.shadow_pass.value=i.map.texture,p.uniforms.resolution.value=i.mapSize,p.uniforms.radius.value=i.radius,t.setRenderTarget(i.mapPass),t.clear(),t.renderBufferDirect(n,null,s,p,g,null),m.uniforms.shadow_pass.value=i.mapPass.texture,m.uniforms.resolution.value=i.mapSize,m.uniforms.radius.value=i.radius,t.setRenderTarget(i.map),t.clear(),t.renderBufferDirect(n,null,s,m,g,null)}function _(e,i,n,r,s,a){let h=null;const d=!0===n.isPointLight?e.customDistanceMaterial:e.customDepthMaterial;if(h=void 0!==d?d:!0===n.isPointLight?l:o,t.localClippingEnabled&&!0===i.clipShadows&&Array.isArray(i.clippingPlanes)&&0!==i.clippingPlanes.length||i.displacementMap&&0!==i.displacementScale||i.alphaMap&&i.alphaTest>0||i.map&&i.alphaTest>0){const t=h.uuid,e=i.uuid;let n=c[t];void 0===n&&(n={},c[t]=n);let r=n[e];void 0===r&&(r=h.clone(),n[e]=r),h=r}return h.visible=i.visible,h.wireframe=i.wireframe,h.side=3===a?null!==i.shadowSide?i.shadowSide:i.side:null!==i.shadowSide?i.shadowSide:u[i.side],h.alphaMap=i.alphaMap,h.alphaTest=i.alphaTest,h.map=i.map,h.clipShadows=i.clipShadows,h.clippingPlanes=i.clippingPlanes,h.clipIntersection=i.clipIntersection,h.displacementMap=i.displacementMap,h.displacementScale=i.displacementScale,h.displacementBias=i.displacementBias,h.wireframeLinewidth=i.wireframeLinewidth,h.linewidth=i.linewidth,!0===n.isPointLight&&!0===h.isMeshDistanceMaterial&&(h.referencePosition.setFromMatrixPosition(n.matrixWorld),h.nearDistance=r,h.farDistance=s),h}function y(i,r,s,a,o){if(!1===i.visible)return;if(i.layers.test(r.layers)&&(i.isMesh||i.isLine||i.isPoints)&&(i.castShadow||i.receiveShadow&&3===o)&&(!i.frustumCulled||n.intersectsObject(i))){i.modelViewMatrix.multiplyMatrices(s.matrixWorldInverse,i.matrixWorld);const n=e.update(i),r=i.material;if(Array.isArray(r)){const e=n.groups;for(let l=0,c=e.length;lh||r.y>h)&&(r.x>h&&(s.x=Math.floor(h/m.x),r.x=s.x*m.x,u.mapSize.x=s.x),r.y>h&&(s.y=Math.floor(h/m.y),r.y=s.y*m.y,u.mapSize.y=s.y)),null===u.map){const t=3!==this.type?{minFilter:d,magFilter:d}:{};u.map=new te(r.x,r.y,t),u.map.texture.name=c.name+".shadowMap",u.camera.updateProjectionMatrix()}t.setRenderTarget(u.map),t.clear();const f=u.getViewportCount();for(let t=0;t=1):-1!==I.indexOf("OpenGL ES")&&(P=parseFloat(/^OpenGL ES (\d)/.exec(I)[1]),R=P>=2);let D=null,N={};const O=t.getParameter(3088),z=t.getParameter(2978),U=(new Qt).fromArray(O),B=(new Qt).fromArray(z);function F(e,i,n){const r=new Uint8Array(4),s=t.createTexture();t.bindTexture(e,s),t.texParameteri(e,10241,9728),t.texParameteri(e,10240,9728);for(let e=0;en||t.height>n)&&(r=n/Math.max(t.width,t.height)),r<1||!0===e){if("undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap){const n=e?Tt:Math.floor,s=n(r*t.width),a=n(r*t.height);void 0===D&&(D=z(s,a));const o=i?z(s,a):D;o.width=s,o.height=a;return o.getContext("2d").drawImage(t,0,0,s,a),console.warn("THREE.WebGLRenderer: Texture has been resized from ("+t.width+"x"+t.height+") to ("+s+"x"+a+")."),o}return"data"in t&&console.warn("THREE.WebGLRenderer: Image in DataTexture is too big ("+t.width+"x"+t.height+")."),t}return t}function B(t){return wt(t.width)&&wt(t.height)}function F(t,e){return t.generateMipmaps&&e&&t.minFilter!==d&&t.minFilter!==f}function k(e){t.generateMipmap(e)}function G(i,n,r,s,a=!1){if(!1===o)return n;if(null!==i){if(void 0!==t[i])return t[i];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+i+"'")}let l=n;return 6403===n&&(5126===r&&(l=33326),5131===r&&(l=33325),5121===r&&(l=33321)),33319===n&&(5126===r&&(l=33328),5131===r&&(l=33327),5121===r&&(l=33323)),6408===n&&(5126===r&&(l=34836),5131===r&&(l=34842),5121===r&&(l=s===ot&&!1===a?35907:32856),32819===r&&(l=32854),32820===r&&(l=32855)),33325!==l&&33326!==l&&33327!==l&&33328!==l&&34842!==l&&34836!==l||e.get("EXT_color_buffer_float"),l}function V(t,e,i){return!0===F(t,i)||t.isFramebufferTexture&&t.minFilter!==d&&t.minFilter!==f?Math.log2(Math.max(e.width,e.height))+1:void 0!==t.mipmaps&&t.mipmaps.length>0?t.mipmaps.length:t.isCompressedTexture&&Array.isArray(t.image)?e.mipmaps.length:1}function H(t){return t===d||t===p||t===m?9728:9729}function W(t){const e=t.target;e.removeEventListener("dispose",W),function(t){const e=n.get(t);if(void 0===e.__webglInit)return;const i=t.source,r=N.get(i);if(r){const n=r[e.__cacheKey];n.usedTimes--,0===n.usedTimes&&q(t),0===Object.keys(r).length&&N.delete(i)}n.remove(t)}(e),e.isVideoTexture&&I.delete(e)}function j(e){const i=e.target;i.removeEventListener("dispose",j),function(e){const i=e.texture,r=n.get(e),s=n.get(i);void 0!==s.__webglTexture&&(t.deleteTexture(s.__webglTexture),a.memory.textures--);e.depthTexture&&e.depthTexture.dispose();if(e.isWebGLCubeRenderTarget)for(let e=0;e<6;e++)t.deleteFramebuffer(r.__webglFramebuffer[e]),r.__webglDepthbuffer&&t.deleteRenderbuffer(r.__webglDepthbuffer[e]);else{if(t.deleteFramebuffer(r.__webglFramebuffer),r.__webglDepthbuffer&&t.deleteRenderbuffer(r.__webglDepthbuffer),r.__webglMultisampledFramebuffer&&t.deleteFramebuffer(r.__webglMultisampledFramebuffer),r.__webglColorRenderbuffer)for(let e=0;e0&&r.__version!==t.version){const i=t.image;if(null===i)console.warn("THREE.WebGLRenderer: Texture marked for update but no image data found.");else{if(!1!==i.complete)return void Q(r,t,e);console.warn("THREE.WebGLRenderer: Texture marked for update but image is incomplete")}}i.bindTexture(3553,r.__webglTexture,33984+e)}const Z={[c]:10497,[h]:33071,[u]:33648},J={[d]:9728,[p]:9984,[m]:9986,[f]:9729,[g]:9985,[v]:9987};function K(i,s,a){if(a?(t.texParameteri(i,10242,Z[s.wrapS]),t.texParameteri(i,10243,Z[s.wrapT]),32879!==i&&35866!==i||t.texParameteri(i,32882,Z[s.wrapR]),t.texParameteri(i,10240,J[s.magFilter]),t.texParameteri(i,10241,J[s.minFilter])):(t.texParameteri(i,10242,33071),t.texParameteri(i,10243,33071),32879!==i&&35866!==i||t.texParameteri(i,32882,33071),s.wrapS===h&&s.wrapT===h||console.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping."),t.texParameteri(i,10240,H(s.magFilter)),t.texParameteri(i,10241,H(s.minFilter)),s.minFilter!==d&&s.minFilter!==f&&console.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.")),!0===e.has("EXT_texture_filter_anisotropic")){const a=e.get("EXT_texture_filter_anisotropic");if(s.type===M&&!1===e.has("OES_texture_float_linear"))return;if(!1===o&&s.type===b&&!1===e.has("OES_texture_half_float_linear"))return;(s.anisotropy>1||n.get(s).__currentAnisotropy)&&(t.texParameterf(i,a.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(s.anisotropy,r.getMaxAnisotropy())),n.get(s).__currentAnisotropy=s.anisotropy)}}function $(e,i){let n=!1;void 0===e.__webglInit&&(e.__webglInit=!0,i.addEventListener("dispose",W));const r=i.source;let s=N.get(r);void 0===s&&(s={},N.set(r,s));const o=function(t){const e=[];return e.push(t.wrapS),e.push(t.wrapT),e.push(t.wrapR||0),e.push(t.magFilter),e.push(t.minFilter),e.push(t.anisotropy),e.push(t.internalFormat),e.push(t.format),e.push(t.type),e.push(t.generateMipmaps),e.push(t.premultiplyAlpha),e.push(t.flipY),e.push(t.unpackAlignment),e.push(t.encoding),e.join()}(i);if(o!==e.__cacheKey){void 0===s[o]&&(s[o]={texture:t.createTexture(),usedTimes:0},a.memory.textures++,n=!0),s[o].usedTimes++;const r=s[e.__cacheKey];void 0!==r&&(s[e.__cacheKey].usedTimes--,0===r.usedTimes&&q(i)),e.__cacheKey=o,e.__webglTexture=s[o].texture}return n}function Q(e,r,a){let l=3553;(r.isDataArrayTexture||r.isCompressedArrayTexture)&&(l=35866),r.isData3DTexture&&(l=32879);const c=$(e,r),u=r.source;i.bindTexture(l,e.__webglTexture,33984+a);const p=n.get(u);if(u.version!==p.__version||!0===c){i.activeTexture(33984+a),t.pixelStorei(37440,r.flipY),t.pixelStorei(37441,r.premultiplyAlpha),t.pixelStorei(3317,r.unpackAlignment),t.pixelStorei(37443,0);const e=function(t){return!o&&(t.wrapS!==h||t.wrapT!==h||t.minFilter!==d&&t.minFilter!==f)}(r)&&!1===B(r.image);let n=U(r.image,e,!1,C);n=st(r,n);const m=B(n)||o,g=s.convert(r.format,r.encoding);let v,x=s.convert(r.type),b=G(r.internalFormat,g,x,r.encoding,r.isVideoTexture);K(l,r,m);const E=r.mipmaps,L=o&&!0!==r.isVideoTexture,R=void 0===p.__version||!0===c,P=V(r,n,m);if(r.isDepthTexture)b=6402,o?b=r.type===M?36012:r.type===y?33190:r.type===w?35056:33189:r.type===M&&console.error("WebGLRenderer: Floating point depth texture requires WebGL2."),r.format===T&&6402===b&&r.type!==_&&r.type!==y&&(console.warn("THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture."),r.type=y,x=s.convert(r.type)),r.format===A&&6402===b&&(b=34041,r.type!==w&&(console.warn("THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture."),r.type=w,x=s.convert(r.type))),R&&(L?i.texStorage2D(3553,1,b,n.width,n.height):i.texImage2D(3553,0,b,n.width,n.height,0,g,x,null));else if(r.isDataTexture)if(E.length>0&&m){L&&R&&i.texStorage2D(3553,P,b,E[0].width,E[0].height);for(let t=0,e=E.length;t>=1,e>>=1}}else if(E.length>0&&m){L&&R&&i.texStorage2D(3553,P,b,E[0].width,E[0].height);for(let t=0,e=E.length;t=34069&&l<=34074)&&t.framebufferTexture2D(36160,o,l,n.get(a).__webglTexture,0),i.bindFramebuffer(36160,null)}function et(e,i,n){if(t.bindRenderbuffer(36161,e),i.depthBuffer&&!i.stencilBuffer){let r=33189;if(n||rt(i)){const e=i.depthTexture;e&&e.isDepthTexture&&(e.type===M?r=36012:e.type===y&&(r=33190));const n=nt(i);rt(i)?R.renderbufferStorageMultisampleEXT(36161,n,r,i.width,i.height):t.renderbufferStorageMultisample(36161,n,r,i.width,i.height)}else t.renderbufferStorage(36161,r,i.width,i.height);t.framebufferRenderbuffer(36160,36096,36161,e)}else if(i.depthBuffer&&i.stencilBuffer){const r=nt(i);n&&!1===rt(i)?t.renderbufferStorageMultisample(36161,r,35056,i.width,i.height):rt(i)?R.renderbufferStorageMultisampleEXT(36161,r,35056,i.width,i.height):t.renderbufferStorage(36161,34041,i.width,i.height),t.framebufferRenderbuffer(36160,33306,36161,e)}else{const e=!0===i.isWebGLMultipleRenderTargets?i.texture:[i.texture];for(let r=0;r0&&!0===e.has("WEBGL_multisampled_render_to_texture")&&!1!==i.__useRenderToTexture}function st(t,i){const n=t.encoding,r=t.format,s=t.type;return!0===t.isCompressedTexture||!0===t.isVideoTexture||t.format===pt||n!==at&&(n===ot?!1===o?!0===e.has("EXT_sRGB")&&r===S?(t.format=pt,t.minFilter=f,t.generateMipmaps=!1):i=Yt.sRGBToLinear(i):r===S&&s===x||console.warn("THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType."):console.error("THREE.WebGLTextures: Unsupported texture encoding:",n)),i}this.allocateTextureUnit=function(){const t=X;return t>=l&&console.warn("THREE.WebGLTextures: Trying to use "+t+" texture units while this GPU supports only "+l),X+=1,t},this.resetTextureUnits=function(){X=0},this.setTexture2D=Y,this.setTexture2DArray=function(t,e){const r=n.get(t);t.version>0&&r.__version!==t.version?Q(r,t,e):i.bindTexture(35866,r.__webglTexture,33984+e)},this.setTexture3D=function(t,e){const r=n.get(t);t.version>0&&r.__version!==t.version?Q(r,t,e):i.bindTexture(32879,r.__webglTexture,33984+e)},this.setTextureCube=function(e,r){const a=n.get(e);e.version>0&&a.__version!==e.version?function(e,r,a){if(6!==r.image.length)return;const l=$(e,r),c=r.source;i.bindTexture(34067,e.__webglTexture,33984+a);const h=n.get(c);if(c.version!==h.__version||!0===l){i.activeTexture(33984+a),t.pixelStorei(37440,r.flipY),t.pixelStorei(37441,r.premultiplyAlpha),t.pixelStorei(3317,r.unpackAlignment),t.pixelStorei(37443,0);const e=r.isCompressedTexture||r.image[0].isCompressedTexture,n=r.image[0]&&r.image[0].isDataTexture,u=[];for(let t=0;t<6;t++)u[t]=e||n?n?r.image[t].image:r.image[t]:U(r.image[t],!1,!0,E),u[t]=st(r,u[t]);const d=u[0],p=B(d)||o,m=s.convert(r.format,r.encoding),f=s.convert(r.type),g=G(r.internalFormat,m,f,r.encoding),v=o&&!0!==r.isVideoTexture,x=void 0===h.__version||!0===l;let _,y=V(r,d,p);if(K(34067,r,p),e){v&&x&&i.texStorage2D(34067,y,g,d.width,d.height);for(let t=0;t<6;t++){_=u[t].mipmaps;for(let e=0;e<_.length;e++){const n=_[e];r.format!==S?null!==m?v?i.compressedTexSubImage2D(34069+t,e,0,0,n.width,n.height,m,n.data):i.compressedTexImage2D(34069+t,e,g,n.width,n.height,0,n.data):console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()"):v?i.texSubImage2D(34069+t,e,0,0,n.width,n.height,m,f,n.data):i.texImage2D(34069+t,e,g,n.width,n.height,0,m,f,n.data)}}}else{_=r.mipmaps,v&&x&&(_.length>0&&y++,i.texStorage2D(34067,y,g,u[0].width,u[0].height));for(let t=0;t<6;t++)if(n){v?i.texSubImage2D(34069+t,0,0,0,u[t].width,u[t].height,m,f,u[t].data):i.texImage2D(34069+t,0,g,u[t].width,u[t].height,0,m,f,u[t].data);for(let e=0;e<_.length;e++){const n=_[e].image[t].image;v?i.texSubImage2D(34069+t,e+1,0,0,n.width,n.height,m,f,n.data):i.texImage2D(34069+t,e+1,g,n.width,n.height,0,m,f,n.data)}}else{v?i.texSubImage2D(34069+t,0,0,0,m,f,u[t]):i.texImage2D(34069+t,0,g,m,f,u[t]);for(let e=0;e<_.length;e++){const n=_[e];v?i.texSubImage2D(34069+t,e+1,0,0,m,f,n.image[t]):i.texImage2D(34069+t,e+1,g,m,f,n.image[t])}}}F(r,p)&&k(34067),h.__version=c.version,r.onUpdate&&r.onUpdate(r)}e.__version=r.version}(a,e,r):i.bindTexture(34067,a.__webglTexture,33984+r)},this.rebindTextures=function(t,e,i){const r=n.get(t);void 0!==e&&tt(r.__webglFramebuffer,t,t.texture,36064,3553),void 0!==i&&it(t)},this.setupRenderTarget=function(e){const l=e.texture,c=n.get(e),h=n.get(l);e.addEventListener("dispose",j),!0!==e.isWebGLMultipleRenderTargets&&(void 0===h.__webglTexture&&(h.__webglTexture=t.createTexture()),h.__version=l.version,a.memory.textures++);const u=!0===e.isWebGLCubeRenderTarget,d=!0===e.isWebGLMultipleRenderTargets,p=B(e)||o;if(u){c.__webglFramebuffer=[];for(let e=0;e<6;e++)c.__webglFramebuffer[e]=t.createFramebuffer()}else{if(c.__webglFramebuffer=t.createFramebuffer(),d)if(r.drawBuffers){const i=e.texture;for(let e=0,r=i.length;e0&&!1===rt(e)){const n=d?l:[l];c.__webglMultisampledFramebuffer=t.createFramebuffer(),c.__webglColorRenderbuffer=[],i.bindFramebuffer(36160,c.__webglMultisampledFramebuffer);for(let i=0;i0&&!1===rt(e)){const r=e.isWebGLMultipleRenderTargets?e.texture:[e.texture],s=e.width,a=e.height;let o=16384;const l=[],c=e.stencilBuffer?33306:36096,h=n.get(e),u=!0===e.isWebGLMultipleRenderTargets;if(u)for(let e=0;eo+c?(l.inputState.pinching=!1,this.dispatchEvent({type:"pinchend",handedness:t.handedness,target:this})):!l.inputState.pinching&&a<=o-c&&(l.inputState.pinching=!0,this.dispatchEvent({type:"pinchstart",handedness:t.handedness,target:this}))}else null!==o&&t.gripSpace&&(r=e.getPose(t.gripSpace,i),null!==r&&(o.matrix.fromArray(r.transform.matrix),o.matrix.decompose(o.position,o.rotation,o.scale),r.linearVelocity?(o.hasLinearVelocity=!0,o.linearVelocity.copy(r.linearVelocity)):o.hasLinearVelocity=!1,r.angularVelocity?(o.hasAngularVelocity=!0,o.angularVelocity.copy(r.angularVelocity)):o.hasAngularVelocity=!1));null!==a&&(n=e.getPose(t.targetRaySpace,i),null===n&&null!==r&&(n=r),null!==n&&(a.matrix.fromArray(n.transform.matrix),a.matrix.decompose(a.position,a.rotation,a.scale),n.linearVelocity?(a.hasLinearVelocity=!0,a.linearVelocity.copy(n.linearVelocity)):a.hasLinearVelocity=!1,n.angularVelocity?(a.hasAngularVelocity=!0,a.angularVelocity.copy(n.angularVelocity)):a.hasAngularVelocity=!1,this.dispatchEvent(Ys)))}return null!==a&&(a.visible=null!==n),null!==o&&(o.visible=null!==r),null!==l&&(l.visible=null!==s),this}_getHandJoint(t,e){if(void 0===t.joints[e.jointName]){const i=new Hs;i.matrixAutoUpdate=!1,i.visible=!1,t.joints[e.jointName]=i,t.add(i)}return t.joints[e.jointName]}}class Js extends $t{constructor(t,e,i,n,r,s,a,o,l,c){if((c=void 0!==c?c:T)!==T&&c!==A)throw new Error("DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat");void 0===i&&c===T&&(i=y),void 0===i&&c===A&&(i=w),super(null,n,r,s,a,o,c,i,l),this.isDepthTexture=!0,this.image={width:t,height:e},this.magFilter=void 0!==a?a:d,this.minFilter=void 0!==o?o:d,this.flipY=!1,this.generateMipmaps=!1}}class Ks extends mt{constructor(t,e){super();const i=this;let n=null,r=1;var s=null;let a=null,o="local-floor",l=null,c=null;var h=[];let u=null,d=null,p=null,m=null;const f=e.getContextAttributes();let g=null,v=null;const _=[],M=[],b=new Set,E=new Map,C=new on;C.layers.enable(1),C.viewport=new Qt;const L=new on;L.layers.enable(2),L.viewport=new Qt;const R=[C,L],P=new Ws;P.layers.enable(1),P.layers.enable(2);let I=null,D=null;function N(t){const e=M.indexOf(t.inputSource);if(-1===e)return;const i=_[e];void 0!==i&&i.dispatchEvent({type:t.type,data:t.inputSource})}function O(){n.removeEventListener("select",N),n.removeEventListener("selectstart",N),n.removeEventListener("selectend",N),n.removeEventListener("squeeze",N),n.removeEventListener("squeezestart",N),n.removeEventListener("squeezeend",N),n.removeEventListener("end",O),n.removeEventListener("inputsourceschange",z);for(let t=0;t<_.length;t++){const e=M[t];null!==e&&(M[t]=null,_[t].disconnect(e))}I=null,D=null,t.setRenderTarget(g),p=null,d=null,u=null,n=null,v=null,G.stop(),i.isPresenting=!1,i.dispatchEvent({type:"sessionend"})}function z(t){for(let e=0;e=0&&(M[n]=null,_[n].disconnect(i))}for(let e=0;e=M.length){M.push(i),n=t;break}if(null===M[t]){M[t]=i,n=t;break}}if(-1===n)break}const r=_[n];r&&r.connect(i)}}this.cameraAutoUpdate=!0,this.layersEnabled=!1,this.enabled=!1,this.isPresenting=!1,this.getCameraPose=function(){return c},this.getController=function(t){let e=_[t];return void 0===e&&(e=new Zs,_[t]=e),e.getTargetRaySpace()},this.getControllerGrip=function(t){let e=_[t];return void 0===e&&(e=new Zs,_[t]=e),e.getGripSpace()},this.getHand=function(t){let e=_[t];return void 0===e&&(e=new Zs,_[t]=e),e.getHandSpace()},this.setFramebufferScaleFactor=function(t){r=t,!0===i.isPresenting&&console.warn("THREE.WebXRManager: Cannot change framebuffer scale while presenting.")},this.setReferenceSpaceType=function(t){o=t,!0===i.isPresenting&&console.warn("THREE.WebXRManager: Cannot change reference space type while presenting.")},this.getReferenceSpace=function(){return l||a},this.setReferenceSpace=function(t){l=t},this.getBaseLayer=function(){return null!==d?d:p},this.getBinding=function(){return u},this.getFrame=function(){return m},this.getSession=function(){return n},this.setSession=async function(s){if(n=s,null!==n){if(g=t.getRenderTarget(),n.addEventListener("select",N),n.addEventListener("selectstart",N),n.addEventListener("selectend",N),n.addEventListener("squeeze",N),n.addEventListener("squeezestart",N),n.addEventListener("squeezeend",N),n.addEventListener("end",O),n.addEventListener("inputsourceschange",z),!0!==f.xrCompatible&&await e.makeXRCompatible(),void 0===n.renderState.layers||!1===t.capabilities.isWebGL2){const i={antialias:void 0!==n.renderState.layers||f.antialias,alpha:f.alpha,depth:f.depth,stencil:f.stencil,framebufferScaleFactor:r};p=new XRWebGLLayer(n,e,i),n.updateRenderState({baseLayer:p}),v=new te(p.framebufferWidth,p.framebufferHeight,{format:S,type:x,encoding:t.outputEncoding,stencilBuffer:f.stencil})}else{let i=null,s=null,a=null;f.depth&&(a=f.stencil?35056:33190,i=f.stencil?A:T,s=f.stencil?w:y);const o={colorFormat:32856,depthFormat:a,scaleFactor:r};u=new XRWebGLBinding(n,e),d=u.createProjectionLayer(o),n.updateRenderState({layers:[d]}),v=new te(d.textureWidth,d.textureHeight,{format:S,type:x,depthTexture:new Js(d.textureWidth,d.textureHeight,s,void 0,void 0,void 0,void 0,void 0,void 0,i),stencilBuffer:f.stencil,encoding:t.outputEncoding,samples:f.antialias?4:0});t.properties.get(v).__ignoreDepthValues=d.ignoreDepthValues}v.isXRRenderTarget=!0,this.setFoveation(1),l=null,a=await n.requestReferenceSpace(o),G.setContext(n),G.start(),i.isPresenting=!0,i.dispatchEvent({type:"sessionstart"})}},this.addLayer=function(t){window.XRWebGLBinding&&this.layersEnabled&&n&&(h.push(t),this.updateLayers())},this.removeLayer=function(t){h.splice(h.indexOf(t),1),window.XRWebGLBinding&&this.layersEnabled&&n&&this.updateLayers()},this.updateLayers=function(){var t=h.map((function(t){return t}));t.unshift(n.renderState.layers[0]),n.updateRenderState({layers:t})};const U=new re,B=new re;function F(t,e){null===e?t.matrixWorld.copy(t.matrix):t.matrixWorld.multiplyMatrices(e.matrixWorld,t.matrix),t.matrixWorldInverse.copy(t.matrixWorld).invert()}this.setPoseTarget=function(t){void 0!==t&&(s=t)},this.updateCamera=function(t){if(null===n)return;P.near=L.near=C.near=t.near,P.far=L.far=C.far=t.far,I===P.near&&D===P.far||(n.updateRenderState({depthNear:P.near,depthFar:P.far}),I=P.near,D=P.far);const e=P.cameras;var i=s||t;const r=i.parent;F(P,r);for(let t=0;te&&(E.set(t,t.lastChangedTime),i.dispatchEvent({type:"planechanged",data:t}))}else b.add(t),E.set(t,n.lastChangedTime),i.dispatchEvent({type:"planeadded",data:t})}m=null})),this.setAnimationLoop=function(t){k=t},this.dispose=function(){}}}function $s(t,e){function i(i,n){i.opacity.value=n.opacity,n.color&&i.diffuse.value.copy(n.color),n.emissive&&i.emissive.value.copy(n.emissive).multiplyScalar(n.emissiveIntensity),n.map&&(i.map.value=n.map),n.alphaMap&&(i.alphaMap.value=n.alphaMap),n.bumpMap&&(i.bumpMap.value=n.bumpMap,i.bumpScale.value=n.bumpScale,1===n.side&&(i.bumpScale.value*=-1)),n.displacementMap&&(i.displacementMap.value=n.displacementMap,i.displacementScale.value=n.displacementScale,i.displacementBias.value=n.displacementBias),n.emissiveMap&&(i.emissiveMap.value=n.emissiveMap),n.normalMap&&(i.normalMap.value=n.normalMap,i.normalScale.value.copy(n.normalScale),1===n.side&&i.normalScale.value.negate()),n.specularMap&&(i.specularMap.value=n.specularMap),n.alphaTest>0&&(i.alphaTest.value=n.alphaTest);const r=e.get(n).envMap;if(r&&(i.envMap.value=r,i.flipEnvMap.value=r.isCubeTexture&&!1===r.isRenderTargetTexture?-1:1,i.reflectivity.value=n.reflectivity,i.ior.value=n.ior,i.refractionRatio.value=n.refractionRatio),n.lightMap){i.lightMap.value=n.lightMap;const e=!0!==t.physicallyCorrectLights?Math.PI:1;i.lightMapIntensity.value=n.lightMapIntensity*e}let s,a;n.aoMap&&(i.aoMap.value=n.aoMap,i.aoMapIntensity.value=n.aoMapIntensity),n.map?s=n.map:n.specularMap?s=n.specularMap:n.displacementMap?s=n.displacementMap:n.normalMap?s=n.normalMap:n.bumpMap?s=n.bumpMap:n.roughnessMap?s=n.roughnessMap:n.metalnessMap?s=n.metalnessMap:n.alphaMap?s=n.alphaMap:n.emissiveMap?s=n.emissiveMap:n.clearcoatMap?s=n.clearcoatMap:n.clearcoatNormalMap?s=n.clearcoatNormalMap:n.clearcoatRoughnessMap?s=n.clearcoatRoughnessMap:n.iridescenceMap?s=n.iridescenceMap:n.iridescenceThicknessMap?s=n.iridescenceThicknessMap:n.specularIntensityMap?s=n.specularIntensityMap:n.specularColorMap?s=n.specularColorMap:n.transmissionMap?s=n.transmissionMap:n.thicknessMap?s=n.thicknessMap:n.sheenColorMap?s=n.sheenColorMap:n.sheenRoughnessMap&&(s=n.sheenRoughnessMap),void 0!==s&&(s.isWebGLRenderTarget&&(s=s.texture),!0===s.matrixAutoUpdate&&s.updateMatrix(),i.uvTransform.value.copy(s.matrix)),n.aoMap?a=n.aoMap:n.lightMap&&(a=n.lightMap),void 0!==a&&(a.isWebGLRenderTarget&&(a=a.texture),!0===a.matrixAutoUpdate&&a.updateMatrix(),i.uv2Transform.value.copy(a.matrix))}return{refreshFogUniforms:function(e,i){i.color.getRGB(e.fogColor.value,nn(t)),i.isFog?(e.fogNear.value=i.near,e.fogFar.value=i.far):i.isFogExp2&&(e.fogDensity.value=i.density)},refreshMaterialUniforms:function(t,n,r,s,a){n.isMeshBasicMaterial||n.isMeshLambertMaterial?i(t,n):n.isMeshToonMaterial?(i(t,n),function(t,e){e.gradientMap&&(t.gradientMap.value=e.gradientMap)}(t,n)):n.isMeshPhongMaterial?(i(t,n),function(t,e){t.specular.value.copy(e.specular),t.shininess.value=Math.max(e.shininess,1e-4)}(t,n)):n.isMeshStandardMaterial?(i(t,n),function(t,i){t.roughness.value=i.roughness,t.metalness.value=i.metalness,i.roughnessMap&&(t.roughnessMap.value=i.roughnessMap);i.metalnessMap&&(t.metalnessMap.value=i.metalnessMap);e.get(i).envMap&&(t.envMapIntensity.value=i.envMapIntensity)}(t,n),n.isMeshPhysicalMaterial&&function(t,e,i){t.ior.value=e.ior,e.sheen>0&&(t.sheenColor.value.copy(e.sheenColor).multiplyScalar(e.sheen),t.sheenRoughness.value=e.sheenRoughness,e.sheenColorMap&&(t.sheenColorMap.value=e.sheenColorMap),e.sheenRoughnessMap&&(t.sheenRoughnessMap.value=e.sheenRoughnessMap));e.clearcoat>0&&(t.clearcoat.value=e.clearcoat,t.clearcoatRoughness.value=e.clearcoatRoughness,e.clearcoatMap&&(t.clearcoatMap.value=e.clearcoatMap),e.clearcoatRoughnessMap&&(t.clearcoatRoughnessMap.value=e.clearcoatRoughnessMap),e.clearcoatNormalMap&&(t.clearcoatNormalScale.value.copy(e.clearcoatNormalScale),t.clearcoatNormalMap.value=e.clearcoatNormalMap,1===e.side&&t.clearcoatNormalScale.value.negate()));e.iridescence>0&&(t.iridescence.value=e.iridescence,t.iridescenceIOR.value=e.iridescenceIOR,t.iridescenceThicknessMinimum.value=e.iridescenceThicknessRange[0],t.iridescenceThicknessMaximum.value=e.iridescenceThicknessRange[1],e.iridescenceMap&&(t.iridescenceMap.value=e.iridescenceMap),e.iridescenceThicknessMap&&(t.iridescenceThicknessMap.value=e.iridescenceThicknessMap));e.transmission>0&&(t.transmission.value=e.transmission,t.transmissionSamplerMap.value=i.texture,t.transmissionSamplerSize.value.set(i.width,i.height),e.transmissionMap&&(t.transmissionMap.value=e.transmissionMap),t.thickness.value=e.thickness,e.thicknessMap&&(t.thicknessMap.value=e.thicknessMap),t.attenuationDistance.value=e.attenuationDistance,t.attenuationColor.value.copy(e.attenuationColor));t.specularIntensity.value=e.specularIntensity,t.specularColor.value.copy(e.specularColor),e.specularIntensityMap&&(t.specularIntensityMap.value=e.specularIntensityMap);e.specularColorMap&&(t.specularColorMap.value=e.specularColorMap)}(t,n,a)):n.isMeshMatcapMaterial?(i(t,n),function(t,e){e.matcap&&(t.matcap.value=e.matcap)}(t,n)):n.isMeshDepthMaterial?i(t,n):n.isMeshDistanceMaterial?(i(t,n),function(t,e){t.referencePosition.value.copy(e.referencePosition),t.nearDistance.value=e.nearDistance,t.farDistance.value=e.farDistance}(t,n)):n.isMeshNormalMaterial?i(t,n):n.isLineBasicMaterial?(function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity}(t,n),n.isLineDashedMaterial&&function(t,e){t.dashSize.value=e.dashSize,t.totalSize.value=e.dashSize+e.gapSize,t.scale.value=e.scale}(t,n)):n.isPointsMaterial?function(t,e,i,n){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,t.size.value=e.size*i,t.scale.value=.5*n,e.map&&(t.map.value=e.map);e.alphaMap&&(t.alphaMap.value=e.alphaMap);e.alphaTest>0&&(t.alphaTest.value=e.alphaTest);let r;e.map?r=e.map:e.alphaMap&&(r=e.alphaMap);void 0!==r&&(!0===r.matrixAutoUpdate&&r.updateMatrix(),t.uvTransform.value.copy(r.matrix))}(t,n,r,s):n.isSpriteMaterial?function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,t.rotation.value=e.rotation,e.map&&(t.map.value=e.map);e.alphaMap&&(t.alphaMap.value=e.alphaMap);e.alphaTest>0&&(t.alphaTest.value=e.alphaTest);let i;e.map?i=e.map:e.alphaMap&&(i=e.alphaMap);void 0!==i&&(!0===i.matrixAutoUpdate&&i.updateMatrix(),t.uvTransform.value.copy(i.matrix))}(t,n):n.isShadowMaterial?(t.color.value.copy(n.color),t.opacity.value=n.opacity):n.isShaderMaterial&&(n.uniformsNeedUpdate=!1)}}}function Qs(t,e,i,n){let r={},s={},a=[];const o=i.isWebGL2?t.getParameter(35375):0;function l(t,e,i){const n=t.value;if(void 0===i[e])return i[e]="number"==typeof n?n:n.clone(),!0;if("number"==typeof n){if(i[e]!==n)return i[e]=n,!0}else{const t=i[e];if(!1===t.equals(n))return t.copy(n),!0}return!1}function c(t){const e=t.value,i={boundary:0,storage:0};return"number"==typeof e?(i.boundary=4,i.storage=4):e.isVector2?(i.boundary=8,i.storage=8):e.isVector3||e.isColor?(i.boundary=16,i.storage=12):e.isVector4?(i.boundary=16,i.storage=16):e.isMatrix3?(i.boundary=48,i.storage=48):e.isMatrix4?(i.boundary=64,i.storage=64):e.isTexture?console.warn("THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group."):console.warn("THREE.WebGLRenderer: Unsupported uniform value type.",e),i}function h(e){const i=e.target;i.removeEventListener("dispose",h);const n=a.indexOf(i.__bindingPointIndex);a.splice(n,1),t.deleteBuffer(r[i.id]),delete r[i.id],delete s[i.id]}return{bind:function(t,e){const i=e.program;n.uniformBlockBinding(t,i)},update:function(i,u){let d=r[i.id];void 0===d&&(!function(t){const e=t.uniforms;let i=0;const n=16;let r=0;for(let t=0,s=e.length;t0){r=i%n;const t=n-r;0!==r&&t-a.boundary<0&&(i+=n-r,s.__offset=i)}i+=a.storage}r=i%n,r>0&&(i+=n-r);t.__size=i,t.__cache={}}(i),d=function(e){const i=function(){for(let t=0;t0&&function(t,e,i){const n=Y.isWebGL2;null===G&&(G=new te(1,1,{generateMipmaps:!0,type:X.has("EXT_color_buffer_half_float")?b:x,minFilter:v,samples:n&&!0===s?4:0}));f.getDrawingBufferSize(H),n?G.setSize(H.x,H.y):G.setSize(Tt(H.x),Tt(H.y));const r=f.getRenderTarget();f.setRenderTarget(G),f.clear();const a=f.toneMapping;f.toneMapping=0,Nt(t,e,i),f.toneMapping=a,$.updateMultisampleRenderTarget(G),$.updateRenderTargetMipmap(G),f.setRenderTarget(r)}(r,e,i),n&&Z.viewport(E.copy(n)),r.length>0&&Nt(r,e,i),a.length>0&&Nt(a,e,i),o.length>0&&Nt(o,e,i),Z.buffers.depth.setTest(!0),Z.buffers.depth.setMask(!0),Z.buffers.color.setMask(!0),Z.setPolygonOffset(!1)}function Nt(t,e,i){const n=!0===e.isScene?e.overrideMaterial:null;for(let r=0,s=t.length;r0?m[m.length-1]:null,p.pop(),u=p.length>0?p[p.length-1]:null},this.setTexture2D=(Ft=!1,function(t,e){t&&t.isWebGLRenderTarget&&(Ft||(console.warn("THREE.WebGLRenderer.setTexture2D: don't use render targets as textures. Use their .texture property instead."),Ft=!0),t=t.texture),$.setTexture2D(t,e)}),this.getActiveCubeFace=function(){return _},this.getActiveMipmapLevel=function(){return y},this.getRenderTarget=function(){return w},this.setRenderTargetTextures=function(t,e,i){K.get(t.texture).__webglTexture=e,K.get(t.depthTexture).__webglTexture=i;const n=K.get(t);n.__hasExternalTextures=!0,n.__hasExternalTextures&&(n.__autoAllocateDepthBuffer=void 0===i,n.__autoAllocateDepthBuffer||!0===X.has("WEBGL_multisampled_render_to_texture")&&(console.warn("THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided"),n.__useRenderToTexture=!1))},this.setRenderTargetFramebuffer=function(t,e){const i=K.get(t);i.__webglFramebuffer=e,i.__useDefaultFramebuffer=void 0===e},this.setRenderTarget=function(t,e=0,i=0){w=t,_=e,y=i;let n=!0,r=null,s=!1,a=!1;if(t){const i=K.get(t);void 0!==i.__useDefaultFramebuffer?(Z.bindFramebuffer(36160,null),n=!1):void 0===i.__webglFramebuffer?$.setupRenderTarget(t):i.__hasExternalTextures&&$.rebindTextures(t,K.get(t.texture).__webglTexture,K.get(t.depthTexture).__webglTexture);const o=t.texture;(o.isData3DTexture||o.isDataArrayTexture||o.isCompressedArrayTexture)&&(a=!0);const l=K.get(t).__webglFramebuffer;t.isWebGLCubeRenderTarget?(r=l[e],s=!0):r=Y.isWebGL2&&t.samples>0&&!1===$.useMultisampledRTT(t)?K.get(t).__webglMultisampledFramebuffer:l,E.copy(t.viewport),C.copy(t.scissor),L=t.scissorTest}else E.copy(O).multiplyScalar(I).floor(),C.copy(z).multiplyScalar(I).floor(),L=U;if(Z.bindFramebuffer(36160,r)&&Y.drawBuffers&&n&&Z.drawBuffers(t,r),Z.viewport(E),Z.scissor(C),Z.setScissorTest(L),s){const n=K.get(t.texture);xt.framebufferTexture2D(36160,36064,34069+e,n.__webglTexture,i)}else if(a){const n=K.get(t.texture),r=e||0;xt.framebufferTextureLayer(36160,36064,n.__webglTexture,i||0,r)}T=-1},this.readRenderTargetPixels=function(t,e,i,n,r,s,a){if(!t||!t.isWebGLRenderTarget)return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let o=K.get(t).__webglFramebuffer;if(t.isWebGLCubeRenderTarget&&void 0!==a&&(o=o[a]),o){Z.bindFramebuffer(36160,o);try{const a=t.texture,o=a.format,l=a.type;if(o!==S&&ft.convert(o)!==xt.getParameter(35739))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");const c=l===b&&(X.has("EXT_color_buffer_half_float")||Y.isWebGL2&&X.has("EXT_color_buffer_float"));if(!(l===x||ft.convert(l)===xt.getParameter(35738)||l===M&&(Y.isWebGL2||X.has("OES_texture_float")||X.has("WEBGL_color_buffer_float"))||c))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");e>=0&&e<=t.width-n&&i>=0&&i<=t.height-r&&xt.readPixels(e,i,n,r,ft.convert(o),ft.convert(l),s)}finally{const t=null!==w?K.get(w).__webglFramebuffer:null;Z.bindFramebuffer(36160,t)}}},this.copyFramebufferToTexture=function(t,e,i=0){const n=Math.pow(2,-i),r=Math.floor(e.image.width*n),s=Math.floor(e.image.height*n);$.setTexture2D(e,0),xt.copyTexSubImage2D(3553,i,0,0,t.x,t.y,r,s),Z.unbindTexture()},this.copyTextureToTexture=function(t,e,i,n=0){const r=e.image.width,s=e.image.height,a=ft.convert(i.format),o=ft.convert(i.type);$.setTexture2D(i,0),xt.pixelStorei(37440,i.flipY),xt.pixelStorei(37441,i.premultiplyAlpha),xt.pixelStorei(3317,i.unpackAlignment),e.isDataTexture?xt.texSubImage2D(3553,n,t.x,t.y,r,s,a,o,e.image.data):e.isCompressedTexture?xt.compressedTexSubImage2D(3553,n,t.x,t.y,e.mipmaps[0].width,e.mipmaps[0].height,a,e.mipmaps[0].data):xt.texSubImage2D(3553,n,t.x,t.y,a,o,e.image),0===n&&i.generateMipmaps&&xt.generateMipmap(3553),Z.unbindTexture()},this.copyTextureToTexture3D=function(t,e,i,n,r=0){if(f.isWebGL1Renderer)return void console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.");const s=t.max.x-t.min.x+1,a=t.max.y-t.min.y+1,o=t.max.z-t.min.z+1,l=ft.convert(n.format),c=ft.convert(n.type);let h;if(n.isData3DTexture)$.setTexture3D(n,0),h=32879;else{if(!n.isDataArrayTexture)return void console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.");$.setTexture2DArray(n,0),h=35866}xt.pixelStorei(37440,n.flipY),xt.pixelStorei(37441,n.premultiplyAlpha),xt.pixelStorei(3317,n.unpackAlignment);const u=xt.getParameter(3314),d=xt.getParameter(32878),p=xt.getParameter(3316),m=xt.getParameter(3315),g=xt.getParameter(32877),v=i.isCompressedTexture?i.mipmaps[0]:i.image;xt.pixelStorei(3314,v.width),xt.pixelStorei(32878,v.height),xt.pixelStorei(3316,t.min.x),xt.pixelStorei(3315,t.min.y),xt.pixelStorei(32877,t.min.z),i.isDataTexture||i.isData3DTexture?xt.texSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,c,v.data):i.isCompressedArrayTexture?(console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture."),xt.compressedTexSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,v.data)):xt.texSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,c,v),xt.pixelStorei(3314,u),xt.pixelStorei(32878,d),xt.pixelStorei(3316,p),xt.pixelStorei(3315,m),xt.pixelStorei(32877,g),0===r&&n.generateMipmaps&&xt.generateMipmap(h),Z.unbindTexture()},this.initTexture=function(t){t.isCubeTexture?$.setTextureCube(t,0):t.isData3DTexture?$.setTexture3D(t,0):t.isDataArrayTexture||t.isCompressedArrayTexture?$.setTexture2DArray(t,0):$.setTexture2D(t,0),Z.unbindTexture()},this.resetState=function(){_=0,y=0,w=null,Z.reset(),gt.reset()},"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}class ea extends ta{}ea.prototype.isWebGL1Renderer=!0;class ia{constructor(t,e=25e-5){this.isFogExp2=!0,this.name="",this.color=new qt(t),this.density=e}clone(){return new ia(this.color,this.density)}toJSON(){return{type:"FogExp2",color:this.color.getHex(),density:this.density}}}class na{constructor(t,e=1,i=1e3){this.isFog=!0,this.name="",this.color=new qt(t),this.near=e,this.far=i}clone(){return new na(this.color,this.near,this.far)}toJSON(){return{type:"Fog",color:this.color.getHex(),near:this.near,far:this.far}}}class ra extends si{constructor(){super(),this.isScene=!0,this.type="Scene",this.background=null,this.environment=null,this.fog=null,this.backgroundBlurriness=0,this.backgroundIntensity=1,this.overrideMaterial=null,"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}copy(t,e){return super.copy(t,e),null!==t.background&&(this.background=t.background.clone()),null!==t.environment&&(this.environment=t.environment.clone()),null!==t.fog&&(this.fog=t.fog.clone()),this.backgroundBlurriness=t.backgroundBlurriness,this.backgroundIntensity=t.backgroundIntensity,null!==t.overrideMaterial&&(this.overrideMaterial=t.overrideMaterial.clone()),this.matrixAutoUpdate=t.matrixAutoUpdate,this}toJSON(t){const e=super.toJSON(t);return null!==this.fog&&(e.object.fog=this.fog.toJSON()),this.backgroundBlurriness>0&&(e.backgroundBlurriness=this.backgroundBlurriness),1!==this.backgroundIntensity&&(e.backgroundIntensity=this.backgroundIntensity),e}get autoUpdate(){return console.warn("THREE.Scene: autoUpdate was renamed to matrixWorldAutoUpdate in r144."),this.matrixWorldAutoUpdate}set autoUpdate(t){console.warn("THREE.Scene: autoUpdate was renamed to matrixWorldAutoUpdate in r144."),this.matrixWorldAutoUpdate=t}}class sa{constructor(t,e){this.isInterleavedBuffer=!0,this.array=t,this.stride=e,this.count=void 0!==t?t.length/e:0,this.usage=ut,this.updateRange={offset:0,count:-1},this.version=0,this.uuid=_t()}onUploadCallback(){}set needsUpdate(t){!0===t&&this.version++}setUsage(t){return this.usage=t,this}copy(t){return this.array=new t.array.constructor(t.array),this.count=t.count,this.stride=t.stride,this.usage=t.usage,this}copyAt(t,e,i){t*=this.stride,i*=e.stride;for(let n=0,r=this.stride;nt.far||e.push({distance:o,point:ha.clone(),uv:gi.getUV(ha,ga,va,xa,_a,ya,Ma,new Lt),face:null,object:this})}copy(t,e){return super.copy(t,e),void 0!==t.center&&this.center.copy(t.center),this.material=t.material,this}}function wa(t,e,i,n,r,s){pa.subVectors(t,i).addScalar(.5).multiply(n),void 0!==r?(ma.x=s*pa.x-r*pa.y,ma.y=r*pa.x+s*pa.y):ma.copy(pa),t.copy(e),t.x+=ma.x,t.y+=ma.y,t.applyMatrix4(fa)}const Sa=new re,Ta=new re;class Aa extends si{constructor(){super(),this._currentLevel=0,this.type="LOD",Object.defineProperties(this,{levels:{enumerable:!0,value:[]},isLOD:{value:!0}}),this.autoUpdate=!0}copy(t){super.copy(t,!1);const e=t.levels;for(let t=0,i=e.length;t0){let i,n;for(i=1,n=e.length;i0){Sa.setFromMatrixPosition(this.matrixWorld);const i=t.ray.origin.distanceTo(Sa);this.getObjectForDistance(i).raycast(t,e)}}update(t){const e=this.levels;if(e.length>1){Sa.setFromMatrixPosition(t.matrixWorld),Ta.setFromMatrixPosition(this.matrixWorld);const i=Sa.distanceTo(Ta)/t.zoom;let n,r;for(e[0].object.visible=!0,n=1,r=e.length;n=t))break;e[n-1].object.visible=!1,e[n].object.visible=!0}for(this._currentLevel=n-1;no)continue;u.applyMatrix4(this.matrixWorld);const s=t.ray.origin.distanceTo(u);st.far||e.push({distance:s,point:h.clone().applyMatrix4(this.matrixWorld),index:i,face:null,faceIndex:null,object:this})}}else{for(let i=Math.max(0,s.start),n=Math.min(m.count,s.start+s.count)-1;io)continue;u.applyMatrix4(this.matrixWorld);const n=t.ray.origin.distanceTo(u);nt.far||e.push({distance:n,point:h.clone().applyMatrix4(this.matrixWorld),index:i,face:null,faceIndex:null,object:this})}}}updateMorphTargets(){const t=this.geometry.morphAttributes,e=Object.keys(t);if(e.length>0){const i=t[e[0]];if(void 0!==i){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=i.length;t0){const i=t[e[0]];if(void 0!==i){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=i.length;tr.far)return;s.push({distance:l,distanceToRay:Math.sqrt(o),point:i,index:e,face:null,object:a})}}class co extends $t{constructor(t,e,i,n,r,s,a,o,l,c,h,u){super(null,s,a,o,l,c,n,r,h,u),this.isCompressedTexture=!0,this.image={width:e,height:i},this.mipmaps=t,this.flipY=!1,this.generateMipmaps=!1}}class ho{constructor(){this.type="Curve",this.arcLengthDivisions=200}getPoint(){return console.warn("THREE.Curve: .getPoint() not implemented."),null}getPointAt(t,e){const i=this.getUtoTmapping(t);return this.getPoint(i,e)}getPoints(t=5){const e=[];for(let i=0;i<=t;i++)e.push(this.getPoint(i/t));return e}getSpacedPoints(t=5){const e=[];for(let i=0;i<=t;i++)e.push(this.getPointAt(i/t));return e}getLength(){const t=this.getLengths();return t[t.length-1]}getLengths(t=this.arcLengthDivisions){if(this.cacheArcLengths&&this.cacheArcLengths.length===t+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=!1;const e=[];let i,n=this.getPoint(0),r=0;e.push(0);for(let s=1;s<=t;s++)i=this.getPoint(s/t),r+=i.distanceTo(n),e.push(r),n=i;return this.cacheArcLengths=e,e}updateArcLengths(){this.needsUpdate=!0,this.getLengths()}getUtoTmapping(t,e){const i=this.getLengths();let n=0;const r=i.length;let s;s=e||t*i[r-1];let a,o=0,l=r-1;for(;o<=l;)if(n=Math.floor(o+(l-o)/2),a=i[n]-s,a<0)o=n+1;else{if(!(a>0)){l=n;break}l=n-1}if(n=l,i[n]===s)return n/(r-1);const c=i[n];return(n+(s-c)/(i[n+1]-c))/(r-1)}getTangent(t,e){const i=1e-4;let n=t-i,r=t+i;n<0&&(n=0),r>1&&(r=1);const s=this.getPoint(n),a=this.getPoint(r),o=e||(s.isVector2?new Lt:new re);return o.copy(a).sub(s).normalize(),o}getTangentAt(t,e){const i=this.getUtoTmapping(t);return this.getTangent(i,e)}computeFrenetFrames(t,e){const i=new re,n=[],r=[],s=[],a=new re,o=new Ne;for(let e=0;e<=t;e++){const i=e/t;n[e]=this.getTangentAt(i,new re)}r[0]=new re,s[0]=new re;let l=Number.MAX_VALUE;const c=Math.abs(n[0].x),h=Math.abs(n[0].y),u=Math.abs(n[0].z);c<=l&&(l=c,i.set(1,0,0)),h<=l&&(l=h,i.set(0,1,0)),u<=l&&i.set(0,0,1),a.crossVectors(n[0],i).normalize(),r[0].crossVectors(n[0],a),s[0].crossVectors(n[0],r[0]);for(let e=1;e<=t;e++){if(r[e]=r[e-1].clone(),s[e]=s[e-1].clone(),a.crossVectors(n[e-1],n[e]),a.length()>Number.EPSILON){a.normalize();const t=Math.acos(yt(n[e-1].dot(n[e]),-1,1));r[e].applyMatrix4(o.makeRotationAxis(a,t))}s[e].crossVectors(n[e],r[e])}if(!0===e){let e=Math.acos(yt(r[0].dot(r[t]),-1,1));e/=t,n[0].dot(a.crossVectors(r[0],r[t]))>0&&(e=-e);for(let i=1;i<=t;i++)r[i].applyMatrix4(o.makeRotationAxis(n[i],e*i)),s[i].crossVectors(n[i],r[i])}return{tangents:n,normals:r,binormals:s}}clone(){return(new this.constructor).copy(this)}copy(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}toJSON(){const t={metadata:{version:4.5,type:"Curve",generator:"Curve.toJSON"}};return t.arcLengthDivisions=this.arcLengthDivisions,t.type=this.type,t}fromJSON(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}}class uo extends ho{constructor(t=0,e=0,i=1,n=1,r=0,s=2*Math.PI,a=!1,o=0){super(),this.isEllipseCurve=!0,this.type="EllipseCurve",this.aX=t,this.aY=e,this.xRadius=i,this.yRadius=n,this.aStartAngle=r,this.aEndAngle=s,this.aClockwise=a,this.aRotation=o}getPoint(t,e){const i=e||new Lt,n=2*Math.PI;let r=this.aEndAngle-this.aStartAngle;const s=Math.abs(r)n;)r-=n;r0?0:(Math.floor(Math.abs(l)/r)+1)*r:0===c&&l===r-1&&(l=r-2,c=1),this.closed||l>0?a=n[(l-1)%r]:(fo.subVectors(n[0],n[1]).add(n[0]),a=fo);const h=n[l%r],u=n[(l+1)%r];if(this.closed||l+2n.length-2?n.length-1:s+1],h=n[s>n.length-3?n.length-1:s+2];return i.set(yo(a,o.x,l.x,c.x,h.x),yo(a,o.y,l.y,c.y,h.y)),i}copy(t){super.copy(t),this.points=[];for(let e=0,i=t.points.length;e=i){const t=n[r]-i,s=this.curves[r],a=s.getLength(),o=0===a?0:1-t/a;return s.getPointAt(o,e)}r++}return null}getLength(){const t=this.getCurveLengths();return t[t.length-1]}updateArcLengths(){this.needsUpdate=!0,this.cacheLengths=null,this.getCurveLengths()}getCurveLengths(){if(this.cacheLengths&&this.cacheLengths.length===this.curves.length)return this.cacheLengths;const t=[];let e=0;for(let i=0,n=this.curves.length;i1&&!e[e.length-1].equals(e[0])&&e.push(e[0]),e}copy(t){super.copy(t),this.curves=[];for(let e=0,i=t.curves.length;e0){const t=l.getPoint(0);t.equals(this.currentPoint)||this.lineTo(t.x,t.y)}this.curves.push(l);const c=l.getPoint(1);return this.currentPoint.copy(c),this}copy(t){return super.copy(t),this.currentPoint.copy(t.currentPoint),this}toJSON(){const t=super.toJSON();return t.currentPoint=this.currentPoint.toArray(),t}fromJSON(t){return super.fromJSON(t),this.currentPoint.fromArray(t.currentPoint),this}}class Do extends Di{constructor(t=[new Lt(0,-.5),new Lt(.5,0),new Lt(0,.5)],e=12,i=0,n=2*Math.PI){super(),this.type="LatheGeometry",this.parameters={points:t,segments:e,phiStart:i,phiLength:n},e=Math.floor(e),n=yt(n,0,2*Math.PI);const r=[],s=[],a=[],o=[],l=[],c=1/e,h=new re,u=new Lt,d=new re,p=new re,m=new re;let f=0,g=0;for(let e=0;e<=t.length-1;e++)switch(e){case 0:f=t[e+1].x-t[e].x,g=t[e+1].y-t[e].y,d.x=1*g,d.y=-f,d.z=0*g,m.copy(d),d.normalize(),o.push(d.x,d.y,d.z);break;case t.length-1:o.push(m.x,m.y,m.z);break;default:f=t[e+1].x-t[e].x,g=t[e+1].y-t[e].y,d.x=1*g,d.y=-f,d.z=0*g,p.copy(d),d.x+=m.x,d.y+=m.y,d.z+=m.z,d.normalize(),o.push(d.x,d.y,d.z),m.copy(p)}for(let r=0;r<=e;r++){const d=i+r*c*n,p=Math.sin(d),m=Math.cos(d);for(let i=0;i<=t.length-1;i++){h.x=t[i].x*p,h.y=t[i].y,h.z=t[i].x*m,s.push(h.x,h.y,h.z),u.x=r/e,u.y=i/(t.length-1),a.push(u.x,u.y);const n=o[3*i+0]*p,c=o[3*i+1],d=o[3*i+0]*m;l.push(n,c,d)}}for(let i=0;i0&&v(!0),e>0&&v(!1)),this.setIndex(c),this.setAttribute("position",new Ti(h,3)),this.setAttribute("normal",new Ti(u,3)),this.setAttribute("uv",new Ti(d,2))}static fromJSON(t){return new zo(t.radiusTop,t.radiusBottom,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class Uo extends zo{constructor(t=1,e=1,i=8,n=1,r=!1,s=0,a=2*Math.PI){super(0,t,e,i,n,r,s,a),this.type="ConeGeometry",this.parameters={radius:t,height:e,radialSegments:i,heightSegments:n,openEnded:r,thetaStart:s,thetaLength:a}}static fromJSON(t){return new Uo(t.radius,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class Bo extends Di{constructor(t=[],e=[],i=1,n=0){super(),this.type="PolyhedronGeometry",this.parameters={vertices:t,indices:e,radius:i,detail:n};const r=[],s=[];function a(t,e,i,n){const r=n+1,s=[];for(let n=0;n<=r;n++){s[n]=[];const a=t.clone().lerp(i,n/r),o=e.clone().lerp(i,n/r),l=r-n;for(let t=0;t<=l;t++)s[n][t]=0===t&&n===r?a:a.clone().lerp(o,t/l)}for(let t=0;t.9&&a<.1&&(e<.2&&(s[t+0]+=1),i<.2&&(s[t+2]+=1),n<.2&&(s[t+4]+=1))}}()}(),this.setAttribute("position",new Ti(r,3)),this.setAttribute("normal",new Ti(r.slice(),3)),this.setAttribute("uv",new Ti(s,2)),0===n?this.computeVertexNormals():this.normalizeNormals()}static fromJSON(t){return new Bo(t.vertices,t.indices,t.radius,t.details)}}class Fo extends Bo{constructor(t=1,e=0){const i=(1+Math.sqrt(5))/2,n=1/i;super([-1,-1,-1,-1,-1,1,-1,1,-1,-1,1,1,1,-1,-1,1,-1,1,1,1,-1,1,1,1,0,-n,-i,0,-n,i,0,n,-i,0,n,i,-n,-i,0,-n,i,0,n,-i,0,n,i,0,-i,0,-n,i,0,-n,-i,0,n,i,0,n],[3,11,7,3,7,15,3,15,13,7,19,17,7,17,6,7,6,15,17,4,8,17,8,10,17,10,6,8,0,16,8,16,2,8,2,10,0,12,1,0,1,18,0,18,16,6,10,2,6,2,13,6,13,15,2,16,18,2,18,3,2,3,13,18,1,9,18,9,11,18,11,3,4,14,12,4,12,0,4,0,8,11,9,5,11,5,19,11,19,7,19,5,14,19,14,4,19,4,17,1,12,14,1,14,5,1,5,9],t,e),this.type="DodecahedronGeometry",this.parameters={radius:t,detail:e}}static fromJSON(t){return new Fo(t.radius,t.detail)}}const ko=new re,Go=new re,Vo=new re,Ho=new gi;class Wo extends Di{constructor(t=null,e=1){if(super(),this.type="EdgesGeometry",this.parameters={geometry:t,thresholdAngle:e},null!==t){const i=4,n=Math.pow(10,i),r=Math.cos(vt*e),s=t.getIndex(),a=t.getAttribute("position"),o=s?s.count:a.count,l=[0,0,0],c=["a","b","c"],h=new Array(3),u={},d=[];for(let t=0;t80*i){o=c=t[0],l=h=t[1];for(let e=i;ec&&(c=u),d>h&&(h=d);p=Math.max(c-o,h-l),p=0!==p?32767/p:0}return Zo(s,a,i,o,l,p,0),a};function Xo(t,e,i,n,r){let s,a;if(r===function(t,e,i,n){let r=0;for(let s=e,a=i-n;s0)for(s=e;s=e;s-=n)a=ml(s,t[s],t[s+1],a);return a&&ll(a,a.next)&&(fl(a),a=a.next),a}function Yo(t,e){if(!t)return t;e||(e=t);let i,n=t;do{if(i=!1,n.steiner||!ll(n,n.next)&&0!==ol(n.prev,n,n.next))n=n.next;else{if(fl(n),n=e=n.prev,n===n.next)break;i=!0}}while(i||n!==e);return e}function Zo(t,e,i,n,r,s,a){if(!t)return;!a&&s&&function(t,e,i,n){let r=t;do{0===r.z&&(r.z=nl(r.x,r.y,e,i,n)),r.prevZ=r.prev,r.nextZ=r.next,r=r.next}while(r!==t);r.prevZ.nextZ=null,r.prevZ=null,function(t){let e,i,n,r,s,a,o,l,c=1;do{for(i=t,t=null,s=null,a=0;i;){for(a++,n=i,o=0,e=0;e0||l>0&&n;)0!==o&&(0===l||!n||i.z<=n.z)?(r=i,i=i.nextZ,o--):(r=n,n=n.nextZ,l--),s?s.nextZ=r:t=r,r.prevZ=s,s=r;i=n}s.nextZ=null,c*=2}while(a>1)}(r)}(t,n,r,s);let o,l,c=t;for(;t.prev!==t.next;)if(o=t.prev,l=t.next,s?Ko(t,n,r,s):Jo(t))e.push(o.i/i|0),e.push(t.i/i|0),e.push(l.i/i|0),fl(t),t=l.next,c=l.next;else if((t=l)===c){a?1===a?Zo(t=$o(Yo(t),e,i),e,i,n,r,s,2):2===a&&Qo(t,e,i,n,r,s):Zo(Yo(t),e,i,n,r,s,1);break}}function Jo(t){const e=t.prev,i=t,n=t.next;if(ol(e,i,n)>=0)return!1;const r=e.x,s=i.x,a=n.x,o=e.y,l=i.y,c=n.y,h=rs?r>a?r:a:s>a?s:a,p=o>l?o>c?o:c:l>c?l:c;let m=n.next;for(;m!==e;){if(m.x>=h&&m.x<=d&&m.y>=u&&m.y<=p&&sl(r,o,s,l,a,c,m.x,m.y)&&ol(m.prev,m,m.next)>=0)return!1;m=m.next}return!0}function Ko(t,e,i,n){const r=t.prev,s=t,a=t.next;if(ol(r,s,a)>=0)return!1;const o=r.x,l=s.x,c=a.x,h=r.y,u=s.y,d=a.y,p=ol?o>c?o:c:l>c?l:c,g=h>u?h>d?h:d:u>d?u:d,v=nl(p,m,e,i,n),x=nl(f,g,e,i,n);let _=t.prevZ,y=t.nextZ;for(;_&&_.z>=v&&y&&y.z<=x;){if(_.x>=p&&_.x<=f&&_.y>=m&&_.y<=g&&_!==r&&_!==a&&sl(o,h,l,u,c,d,_.x,_.y)&&ol(_.prev,_,_.next)>=0)return!1;if(_=_.prevZ,y.x>=p&&y.x<=f&&y.y>=m&&y.y<=g&&y!==r&&y!==a&&sl(o,h,l,u,c,d,y.x,y.y)&&ol(y.prev,y,y.next)>=0)return!1;y=y.nextZ}for(;_&&_.z>=v;){if(_.x>=p&&_.x<=f&&_.y>=m&&_.y<=g&&_!==r&&_!==a&&sl(o,h,l,u,c,d,_.x,_.y)&&ol(_.prev,_,_.next)>=0)return!1;_=_.prevZ}for(;y&&y.z<=x;){if(y.x>=p&&y.x<=f&&y.y>=m&&y.y<=g&&y!==r&&y!==a&&sl(o,h,l,u,c,d,y.x,y.y)&&ol(y.prev,y,y.next)>=0)return!1;y=y.nextZ}return!0}function $o(t,e,i){let n=t;do{const r=n.prev,s=n.next.next;!ll(r,s)&&cl(r,n,n.next,s)&&dl(r,s)&&dl(s,r)&&(e.push(r.i/i|0),e.push(n.i/i|0),e.push(s.i/i|0),fl(n),fl(n.next),n=t=s),n=n.next}while(n!==t);return Yo(n)}function Qo(t,e,i,n,r,s){let a=t;do{let t=a.next.next;for(;t!==a.prev;){if(a.i!==t.i&&al(a,t)){let o=pl(a,t);return a=Yo(a,a.next),o=Yo(o,o.next),Zo(a,e,i,n,r,s,0),void Zo(o,e,i,n,r,s,0)}t=t.next}a=a.next}while(a!==t)}function tl(t,e){return t.x-e.x}function el(t,e){const i=function(t,e){let i,n=e,r=-1/0;const s=t.x,a=t.y;do{if(a<=n.y&&a>=n.next.y&&n.next.y!==n.y){const t=n.x+(a-n.y)*(n.next.x-n.x)/(n.next.y-n.y);if(t<=s&&t>r&&(r=t,i=n.x=n.x&&n.x>=l&&s!==n.x&&sl(ai.x||n.x===i.x&&il(i,n)))&&(i=n,u=h)),n=n.next}while(n!==o);return i}(t,e);if(!i)return e;const n=pl(i,t);return Yo(n,n.next),Yo(i,i.next)}function il(t,e){return ol(t.prev,t,e.prev)<0&&ol(e.next,t,t.next)<0}function nl(t,e,i,n,r){return(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=(t-i)*r|0)|t<<8))|t<<4))|t<<2))|t<<1))|(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=(e-n)*r|0)|e<<8))|e<<4))|e<<2))|e<<1))<<1}function rl(t){let e=t,i=t;do{(e.x=(t-a)*(s-o)&&(t-a)*(n-o)>=(i-a)*(e-o)&&(i-a)*(s-o)>=(r-a)*(n-o)}function al(t,e){return t.next.i!==e.i&&t.prev.i!==e.i&&!function(t,e){let i=t;do{if(i.i!==t.i&&i.next.i!==t.i&&i.i!==e.i&&i.next.i!==e.i&&cl(i,i.next,t,e))return!0;i=i.next}while(i!==t);return!1}(t,e)&&(dl(t,e)&&dl(e,t)&&function(t,e){let i=t,n=!1;const r=(t.x+e.x)/2,s=(t.y+e.y)/2;do{i.y>s!=i.next.y>s&&i.next.y!==i.y&&r<(i.next.x-i.x)*(s-i.y)/(i.next.y-i.y)+i.x&&(n=!n),i=i.next}while(i!==t);return n}(t,e)&&(ol(t.prev,t,e.prev)||ol(t,e.prev,e))||ll(t,e)&&ol(t.prev,t,t.next)>0&&ol(e.prev,e,e.next)>0)}function ol(t,e,i){return(e.y-t.y)*(i.x-e.x)-(e.x-t.x)*(i.y-e.y)}function ll(t,e){return t.x===e.x&&t.y===e.y}function cl(t,e,i,n){const r=ul(ol(t,e,i)),s=ul(ol(t,e,n)),a=ul(ol(i,n,t)),o=ul(ol(i,n,e));return r!==s&&a!==o||(!(0!==r||!hl(t,i,e))||(!(0!==s||!hl(t,n,e))||(!(0!==a||!hl(i,t,n))||!(0!==o||!hl(i,e,n)))))}function hl(t,e,i){return e.x<=Math.max(t.x,i.x)&&e.x>=Math.min(t.x,i.x)&&e.y<=Math.max(t.y,i.y)&&e.y>=Math.min(t.y,i.y)}function ul(t){return t>0?1:t<0?-1:0}function dl(t,e){return ol(t.prev,t,t.next)<0?ol(t,e,t.next)>=0&&ol(t,t.prev,e)>=0:ol(t,e,t.prev)<0||ol(t,t.next,e)<0}function pl(t,e){const i=new gl(t.i,t.x,t.y),n=new gl(e.i,e.x,e.y),r=t.next,s=e.prev;return t.next=e,e.prev=t,i.next=r,r.prev=i,n.next=i,i.prev=n,s.next=n,n.prev=s,n}function ml(t,e,i,n){const r=new gl(t,e,i);return n?(r.next=n.next,r.prev=n,n.next.prev=r,n.next=r):(r.prev=r,r.next=r),r}function fl(t){t.next.prev=t.prev,t.prev.next=t.next,t.prevZ&&(t.prevZ.nextZ=t.nextZ),t.nextZ&&(t.nextZ.prevZ=t.prevZ)}function gl(t,e,i){this.i=t,this.x=e,this.y=i,this.prev=null,this.next=null,this.z=0,this.prevZ=null,this.nextZ=null,this.steiner=!1}class vl{static area(t){const e=t.length;let i=0;for(let n=e-1,r=0;r2&&t[e-1].equals(t[0])&&t.pop()}function _l(t,e){for(let i=0;iNumber.EPSILON){const u=Math.sqrt(h),d=Math.sqrt(l*l+c*c),p=e.x-o/u,m=e.y+a/u,f=((i.x-c/d-p)*c-(i.y+l/d-m)*l)/(a*c-o*l);n=p+a*f-t.x,r=m+o*f-t.y;const g=n*n+r*r;if(g<=2)return new Lt(n,r);s=Math.sqrt(g/2)}else{let t=!1;a>Number.EPSILON?l>Number.EPSILON&&(t=!0):a<-Number.EPSILON?l<-Number.EPSILON&&(t=!0):Math.sign(o)===Math.sign(c)&&(t=!0),t?(n=-o,r=a,s=Math.sqrt(h)):(n=a,r=o,s=Math.sqrt(h/2))}return new Lt(n/s,r/s)}const P=[];for(let t=0,e=A.length,i=e-1,n=t+1;t=0;t--){const e=t/p,i=h*Math.cos(e*Math.PI/2),n=u*Math.sin(e*Math.PI/2)+d;for(let t=0,e=A.length;t=0;){const n=i;let r=i-1;r<0&&(r=t.length-1);for(let t=0,i=o+2*p;t0)&&d.push(e,r,l),(t!==i-1||o0!=t>0&&this.version++,this._sheen=t}get clearcoat(){return this._clearcoat}set clearcoat(t){this._clearcoat>0!=t>0&&this.version++,this._clearcoat=t}get iridescence(){return this._iridescence}set iridescence(t){this._iridescence>0!=t>0&&this.version++,this._iridescence=t}get transmission(){return this._transmission}set transmission(t){this._transmission>0!=t>0&&this.version++,this._transmission=t}copy(t){return super.copy(t),this.defines={STANDARD:"",PHYSICAL:""},this.clearcoat=t.clearcoat,this.clearcoatMap=t.clearcoatMap,this.clearcoatRoughness=t.clearcoatRoughness,this.clearcoatRoughnessMap=t.clearcoatRoughnessMap,this.clearcoatNormalMap=t.clearcoatNormalMap,this.clearcoatNormalScale.copy(t.clearcoatNormalScale),this.ior=t.ior,this.iridescence=t.iridescence,this.iridescenceMap=t.iridescenceMap,this.iridescenceIOR=t.iridescenceIOR,this.iridescenceThicknessRange=[...t.iridescenceThicknessRange],this.iridescenceThicknessMap=t.iridescenceThicknessMap,this.sheen=t.sheen,this.sheenColor.copy(t.sheenColor),this.sheenColorMap=t.sheenColorMap,this.sheenRoughness=t.sheenRoughness,this.sheenRoughnessMap=t.sheenRoughnessMap,this.transmission=t.transmission,this.transmissionMap=t.transmissionMap,this.thickness=t.thickness,this.thicknessMap=t.thicknessMap,this.attenuationDistance=t.attenuationDistance,this.attenuationColor.copy(t.attenuationColor),this.specularIntensity=t.specularIntensity,this.specularIntensityMap=t.specularIntensityMap,this.specularColor.copy(t.specularColor),this.specularColorMap=t.specularColorMap,this}}class Bl extends xi{constructor(t){super(),this.isMeshPhongMaterial=!0,this.type="MeshPhongMaterial",this.color=new qt(16777215),this.specular=new qt(1118481),this.shininess=30,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new qt(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Lt(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.specular.copy(t.specular),this.shininess=t.shininess,this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.flatShading=t.flatShading,this.fog=t.fog,this}}class Fl extends xi{constructor(t){super(),this.isMeshToonMaterial=!0,this.defines={TOON:""},this.type="MeshToonMaterial",this.color=new qt(16777215),this.map=null,this.gradientMap=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new qt(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Lt(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.gradientMap=t.gradientMap,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.alphaMap=t.alphaMap,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.fog=t.fog,this}}class kl extends xi{constructor(t){super(),this.isMeshNormalMaterial=!0,this.type="MeshNormalMaterial",this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Lt(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.flatShading=!1,this.setValues(t)}copy(t){return super.copy(t),this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.flatShading=t.flatShading,this}}class Gl extends xi{constructor(t){super(),this.isMeshLambertMaterial=!0,this.type="MeshLambertMaterial",this.color=new qt(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new qt(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Lt(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.flatShading=t.flatShading,this.fog=t.fog,this}}class Vl extends xi{constructor(t){super(),this.isMeshMatcapMaterial=!0,this.defines={MATCAP:""},this.type="MeshMatcapMaterial",this.color=new qt(16777215),this.matcap=null,this.map=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Lt(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.defines={MATCAP:""},this.color.copy(t.color),this.matcap=t.matcap,this.map=t.map,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.alphaMap=t.alphaMap,this.flatShading=t.flatShading,this.fog=t.fog,this}}class Hl extends ja{constructor(t){super(),this.isLineDashedMaterial=!0,this.type="LineDashedMaterial",this.scale=1,this.dashSize=3,this.gapSize=1,this.setValues(t)}copy(t){return super.copy(t),this.scale=t.scale,this.dashSize=t.dashSize,this.gapSize=t.gapSize,this}}function Wl(t,e,i){return ql(t)?new t.constructor(t.subarray(e,void 0!==i?i:t.length)):t.slice(e,i)}function jl(t,e,i){return!t||!i&&t.constructor===e?t:"number"==typeof e.BYTES_PER_ELEMENT?new e(t):Array.prototype.slice.call(t)}function ql(t){return ArrayBuffer.isView(t)&&!(t instanceof DataView)}function Xl(t){const e=t.length,i=new Array(e);for(let t=0;t!==e;++t)i[t]=t;return i.sort((function(e,i){return t[e]-t[i]})),i}function Yl(t,e,i){const n=t.length,r=new t.constructor(n);for(let s=0,a=0;a!==n;++s){const n=i[s]*e;for(let i=0;i!==e;++i)r[a++]=t[n+i]}return r}function Zl(t,e,i,n){let r=1,s=t[0];for(;void 0!==s&&void 0===s[n];)s=t[r++];if(void 0===s)return;let a=s[n];if(void 0!==a)if(Array.isArray(a))do{a=s[n],void 0!==a&&(e.push(s.time),i.push.apply(i,a)),s=t[r++]}while(void 0!==s);else if(void 0!==a.toArray)do{a=s[n],void 0!==a&&(e.push(s.time),a.toArray(i,i.length)),s=t[r++]}while(void 0!==s);else do{a=s[n],void 0!==a&&(e.push(s.time),i.push(a)),s=t[r++]}while(void 0!==s)}var Jl=Object.freeze({__proto__:null,arraySlice:Wl,convertArray:jl,isTypedArray:ql,getKeyframeOrder:Xl,sortedArray:Yl,flattenJSON:Zl,subclip:function(t,e,i,n,r=30){const s=t.clone();s.name=e;const a=[];for(let t=0;t=n)){l.push(e.times[t]);for(let i=0;is.tracks[t].times[0]&&(o=s.tracks[t].times[0]);for(let t=0;t=n.times[u]){const t=u*l+o,e=t+l-o;d=Wl(n.values,t,e)}else{const t=n.createInterpolant(),e=o,i=l-o;t.evaluate(s),d=Wl(t.resultBuffer,e,i)}if("quaternion"===r){(new ne).fromArray(d).normalize().conjugate().toArray(d)}const p=a.times.length;for(let t=0;t=r)break t;{const a=e[1];t=r)break e}s=i,i=0}}for(;i>>1;te;)--s;if(++s,0!==r||s!==n){r>=s&&(s=Math.max(s,1),r=s-1);const t=this.getValueSize();this.times=Wl(i,r,s),this.values=Wl(this.values,r*t,s*t)}return this}validate(){let t=!0;const e=this.getValueSize();e-Math.floor(e)!=0&&(console.error("THREE.KeyframeTrack: Invalid value size in track.",this),t=!1);const i=this.times,n=this.values,r=i.length;0===r&&(console.error("THREE.KeyframeTrack: Track is empty.",this),t=!1);let s=null;for(let e=0;e!==r;e++){const n=i[e];if("number"==typeof n&&isNaN(n)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,e,n),t=!1;break}if(null!==s&&s>n){console.error("THREE.KeyframeTrack: Out of order keys.",this,e,n,s),t=!1;break}s=n}if(void 0!==n&&ql(n))for(let e=0,i=n.length;e!==i;++e){const i=n[e];if(isNaN(i)){console.error("THREE.KeyframeTrack: Value is not a valid number.",this,e,i),t=!1;break}}return t}optimize(){const t=Wl(this.times),e=Wl(this.values),i=this.getValueSize(),n=this.getInterpolation()===tt,r=t.length-1;let s=1;for(let a=1;a0){t[s]=t[r];for(let t=r*i,n=s*i,a=0;a!==i;++a)e[n+a]=e[t+a];++s}return s!==t.length?(this.times=Wl(t,0,s),this.values=Wl(e,0,s*i)):(this.times=t,this.values=e),this}clone(){const t=Wl(this.times,0),e=Wl(this.values,0),i=new(0,this.constructor)(this.name,t,e);return i.createInterpolant=this.createInterpolant,i}}ec.prototype.TimeBufferType=Float32Array,ec.prototype.ValueBufferType=Float32Array,ec.prototype.DefaultInterpolation=Q;class ic extends ec{}ic.prototype.ValueTypeName="bool",ic.prototype.ValueBufferType=Array,ic.prototype.DefaultInterpolation=$,ic.prototype.InterpolantFactoryMethodLinear=void 0,ic.prototype.InterpolantFactoryMethodSmooth=void 0;class nc extends ec{}nc.prototype.ValueTypeName="color";class rc extends ec{}rc.prototype.ValueTypeName="number";class sc extends Kl{constructor(t,e,i,n){super(t,e,i,n)}interpolate_(t,e,i,n){const r=this.resultBuffer,s=this.sampleValues,a=this.valueSize,o=(i-e)/(n-e);let l=t*a;for(let t=l+a;l!==t;l+=4)ne.slerpFlat(r,0,s,l-a,s,l,o);return r}}class ac extends ec{InterpolantFactoryMethodLinear(t){return new sc(this.times,this.values,this.getValueSize(),t)}}ac.prototype.ValueTypeName="quaternion",ac.prototype.DefaultInterpolation=Q,ac.prototype.InterpolantFactoryMethodSmooth=void 0;class oc extends ec{}oc.prototype.ValueTypeName="string",oc.prototype.ValueBufferType=Array,oc.prototype.DefaultInterpolation=$,oc.prototype.InterpolantFactoryMethodLinear=void 0,oc.prototype.InterpolantFactoryMethodSmooth=void 0;class lc extends ec{}lc.prototype.ValueTypeName="vector";class cc{constructor(t,e=-1,i,n=2500){this.name=t,this.tracks=i,this.duration=e,this.blendMode=n,this.uuid=_t(),this.duration<0&&this.resetDuration()}static parse(t){const e=[],i=t.tracks,n=1/(t.fps||1);for(let t=0,r=i.length;t!==r;++t)e.push(hc(i[t]).scale(n));const r=new this(t.name,t.duration,e,t.blendMode);return r.uuid=t.uuid,r}static toJSON(t){const e=[],i=t.tracks,n={name:t.name,duration:t.duration,tracks:e,uuid:t.uuid,blendMode:t.blendMode};for(let t=0,n=i.length;t!==n;++t)e.push(ec.toJSON(i[t]));return n}static CreateFromMorphTargetSequence(t,e,i,n){const r=e.length,s=[];for(let t=0;t1){const t=s[1];let e=n[t];e||(n[t]=e=[]),e.push(i)}}const s=[];for(const t in n)s.push(this.CreateFromMorphTargetSequence(t,n[t],e,i));return s}static parseAnimation(t,e){if(!t)return console.error("THREE.AnimationClip: No animation in JSONLoader data."),null;const i=function(t,e,i,n,r){if(0!==i.length){const s=[],a=[];Zl(i,s,a,n),0!==s.length&&r.push(new t(e,s,a))}},n=[],r=t.name||"default",s=t.fps||30,a=t.blendMode;let o=t.length||-1;const l=t.hierarchy||[];for(let t=0;t{e&&e(r),this.manager.itemEnd(t)}),0),r;if(void 0!==fc[t])return void fc[t].push({onLoad:e,onProgress:i,onError:n});fc[t]=[],fc[t].push({onLoad:e,onProgress:i,onError:n});const s=new Request(t,{headers:new Headers(this.requestHeader),credentials:this.withCredentials?"include":"same-origin"}),a=this.mimeType,o=this.responseType;fetch(s).then((e=>{if(200===e.status||0===e.status){if(0===e.status&&console.warn("THREE.FileLoader: HTTP Status 0 received."),"undefined"==typeof ReadableStream||void 0===e.body||void 0===e.body.getReader)return e;const i=fc[t],n=e.body.getReader(),r=e.headers.get("Content-Length")||e.headers.get("X-File-Size"),s=r?parseInt(r):0,a=0!==s;let o=0;const l=new ReadableStream({start(t){!function e(){n.read().then((({done:n,value:r})=>{if(n)t.close();else{o+=r.byteLength;const n=new ProgressEvent("progress",{lengthComputable:a,loaded:o,total:s});for(let t=0,e=i.length;t{switch(o){case"arraybuffer":return t.arrayBuffer();case"blob":return t.blob();case"document":return t.text().then((t=>(new DOMParser).parseFromString(t,a)));case"json":return t.json();default:if(void 0===a)return t.text();{const e=/charset="?([^;"\s]*)"?/i.exec(a),i=e&&e[1]?e[1].toLowerCase():void 0,n=new TextDecoder(i);return t.arrayBuffer().then((t=>n.decode(t)))}}})).then((e=>{uc.add(t,e);const i=fc[t];delete fc[t];for(let t=0,n=i.length;t{const i=fc[t];if(void 0===i)throw this.manager.itemError(t),e;delete fc[t];for(let t=0,n=i.length;t{this.manager.itemEnd(t)})),this.manager.itemStart(t)}setResponseType(t){return this.responseType=t,this}setMimeType(t){return this.mimeType=t,this}}class xc extends mc{constructor(t){super(t)}load(t,e,i,n){void 0!==this.path&&(t=this.path+t),t=this.manager.resolveURL(t);const r=this,s=uc.get(t);if(void 0!==s)return r.manager.itemStart(t),setTimeout((function(){e&&e(s),r.manager.itemEnd(t)}),0),s;const a=Ot("img");function o(){c(),uc.add(t,this),e&&e(this),r.manager.itemEnd(t)}function l(e){c(),n&&n(e),r.manager.itemError(t),r.manager.itemEnd(t)}function c(){a.removeEventListener("load",o,!1),a.removeEventListener("error",l,!1)}return a.addEventListener("load",o,!1),a.addEventListener("error",l,!1),"data:"!==t.slice(0,5)&&void 0!==this.crossOrigin&&(a.crossOrigin=this.crossOrigin),r.manager.itemStart(t),a.src=t,a}}class _c extends si{constructor(t,e=1){super(),this.isLight=!0,this.type="Light",this.color=new qt(t),this.intensity=e}dispose(){}copy(t,e){return super.copy(t,e),this.color.copy(t.color),this.intensity=t.intensity,this}toJSON(t){const e=super.toJSON(t);return e.object.color=this.color.getHex(),e.object.intensity=this.intensity,void 0!==this.groundColor&&(e.object.groundColor=this.groundColor.getHex()),void 0!==this.distance&&(e.object.distance=this.distance),void 0!==this.angle&&(e.object.angle=this.angle),void 0!==this.decay&&(e.object.decay=this.decay),void 0!==this.penumbra&&(e.object.penumbra=this.penumbra),void 0!==this.shadow&&(e.object.shadow=this.shadow.toJSON()),e}}class yc extends _c{constructor(t,e,i){super(t,i),this.isHemisphereLight=!0,this.type="HemisphereLight",this.position.copy(si.DefaultUp),this.updateMatrix(),this.groundColor=new qt(e)}copy(t,e){return super.copy(t,e),this.groundColor.copy(t.groundColor),this}}const Mc=new Ne,bc=new re,wc=new re;class Sc{constructor(t){this.camera=t,this.bias=0,this.normalBias=0,this.radius=1,this.blurSamples=8,this.mapSize=new Lt(512,512),this.map=null,this.mapPass=null,this.matrix=new Ne,this.autoUpdate=!0,this.needsUpdate=!1,this._frustum=new xn,this._frameExtents=new Lt(1,1),this._viewportCount=1,this._viewports=[new Qt(0,0,1,1)]}getViewportCount(){return this._viewportCount}getFrustum(){return this._frustum}updateMatrices(t){const e=this.camera,i=this.matrix;bc.setFromMatrixPosition(t.matrixWorld),e.position.copy(bc),wc.setFromMatrixPosition(t.target.matrixWorld),e.lookAt(wc),e.updateMatrixWorld(),Mc.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this._frustum.setFromProjectionMatrix(Mc),i.set(.5,0,0,.5,0,.5,0,.5,0,0,.5,.5,0,0,0,1),i.multiply(Mc)}getViewport(t){return this._viewports[t]}getFrameExtents(){return this._frameExtents}dispose(){this.map&&this.map.dispose(),this.mapPass&&this.mapPass.dispose()}copy(t){return this.camera=t.camera.clone(),this.bias=t.bias,this.radius=t.radius,this.mapSize.copy(t.mapSize),this}clone(){return(new this.constructor).copy(this)}toJSON(){const t={};return 0!==this.bias&&(t.bias=this.bias),0!==this.normalBias&&(t.normalBias=this.normalBias),1!==this.radius&&(t.radius=this.radius),512===this.mapSize.x&&512===this.mapSize.y||(t.mapSize=this.mapSize.toArray()),t.camera=this.camera.toJSON(!1).object,delete t.camera.matrix,t}}class Tc extends Sc{constructor(){super(new on(50,1,.5,500)),this.isSpotLightShadow=!0,this.focus=1}updateMatrices(t){const e=this.camera,i=2*xt*t.angle*this.focus,n=this.mapSize.width/this.mapSize.height,r=t.distance||e.far;i===e.fov&&n===e.aspect&&r===e.far||(e.fov=i,e.aspect=n,e.far=r,e.updateProjectionMatrix()),super.updateMatrices(t)}copy(t){return super.copy(t),this.focus=t.focus,this}}class Ac extends _c{constructor(t,e,i=0,n=Math.PI/3,r=0,s=2){super(t,e),this.isSpotLight=!0,this.type="SpotLight",this.position.copy(si.DefaultUp),this.updateMatrix(),this.target=new si,this.distance=i,this.angle=n,this.penumbra=r,this.decay=s,this.map=null,this.shadow=new Tc}get power(){return this.intensity*Math.PI}set power(t){this.intensity=t/Math.PI}dispose(){this.shadow.dispose()}copy(t,e){return super.copy(t,e),this.distance=t.distance,this.angle=t.angle,this.penumbra=t.penumbra,this.decay=t.decay,this.target=t.target.clone(),this.shadow=t.shadow.clone(),this}}const Ec=new Ne,Cc=new re,Lc=new re;class Rc extends Sc{constructor(){super(new on(90,1,.5,500)),this.isPointLightShadow=!0,this._frameExtents=new Lt(4,2),this._viewportCount=6,this._viewports=[new Qt(2,1,1,1),new Qt(0,1,1,1),new Qt(3,1,1,1),new Qt(1,1,1,1),new Qt(3,0,1,1),new Qt(1,0,1,1)],this._cubeDirections=[new re(1,0,0),new re(-1,0,0),new re(0,0,1),new re(0,0,-1),new re(0,1,0),new re(0,-1,0)],this._cubeUps=[new re(0,1,0),new re(0,1,0),new re(0,1,0),new re(0,1,0),new re(0,0,1),new re(0,0,-1)]}updateMatrices(t,e=0){const i=this.camera,n=this.matrix,r=t.distance||i.far;r!==i.far&&(i.far=r,i.updateProjectionMatrix()),Cc.setFromMatrixPosition(t.matrixWorld),i.position.copy(Cc),Lc.copy(i.position),Lc.add(this._cubeDirections[e]),i.up.copy(this._cubeUps[e]),i.lookAt(Lc),i.updateMatrixWorld(),n.makeTranslation(-Cc.x,-Cc.y,-Cc.z),Ec.multiplyMatrices(i.projectionMatrix,i.matrixWorldInverse),this._frustum.setFromProjectionMatrix(Ec)}}class Pc extends _c{constructor(t,e,i=0,n=2){super(t,e),this.isPointLight=!0,this.type="PointLight",this.distance=i,this.decay=n,this.shadow=new Rc}get power(){return 4*this.intensity*Math.PI}set power(t){this.intensity=t/(4*Math.PI)}dispose(){this.shadow.dispose()}copy(t,e){return super.copy(t,e),this.distance=t.distance,this.decay=t.decay,this.shadow=t.shadow.clone(),this}}class Ic extends Sc{constructor(){super(new In(-5,5,5,-5,.5,500)),this.isDirectionalLightShadow=!0}}class Dc extends _c{constructor(t,e){super(t,e),this.isDirectionalLight=!0,this.type="DirectionalLight",this.position.copy(si.DefaultUp),this.updateMatrix(),this.target=new si,this.shadow=new Ic}dispose(){this.shadow.dispose()}copy(t){return super.copy(t),this.target=t.target.clone(),this.shadow=t.shadow.clone(),this}}class Nc extends _c{constructor(t,e){super(t,e),this.isAmbientLight=!0,this.type="AmbientLight"}}class Oc extends _c{constructor(t,e,i=10,n=10){super(t,e),this.isRectAreaLight=!0,this.type="RectAreaLight",this.width=i,this.height=n}get power(){return this.intensity*this.width*this.height*Math.PI}set power(t){this.intensity=t/(this.width*this.height*Math.PI)}copy(t){return super.copy(t),this.width=t.width,this.height=t.height,this}toJSON(t){const e=super.toJSON(t);return e.object.width=this.width,e.object.height=this.height,e}}class zc{constructor(){this.isSphericalHarmonics3=!0,this.coefficients=[];for(let t=0;t<9;t++)this.coefficients.push(new re)}set(t){for(let e=0;e<9;e++)this.coefficients[e].copy(t[e]);return this}zero(){for(let t=0;t<9;t++)this.coefficients[t].set(0,0,0);return this}getAt(t,e){const i=t.x,n=t.y,r=t.z,s=this.coefficients;return e.copy(s[0]).multiplyScalar(.282095),e.addScaledVector(s[1],.488603*n),e.addScaledVector(s[2],.488603*r),e.addScaledVector(s[3],.488603*i),e.addScaledVector(s[4],i*n*1.092548),e.addScaledVector(s[5],n*r*1.092548),e.addScaledVector(s[6],.315392*(3*r*r-1)),e.addScaledVector(s[7],i*r*1.092548),e.addScaledVector(s[8],.546274*(i*i-n*n)),e}getIrradianceAt(t,e){const i=t.x,n=t.y,r=t.z,s=this.coefficients;return e.copy(s[0]).multiplyScalar(.886227),e.addScaledVector(s[1],1.023328*n),e.addScaledVector(s[2],1.023328*r),e.addScaledVector(s[3],1.023328*i),e.addScaledVector(s[4],.858086*i*n),e.addScaledVector(s[5],.858086*n*r),e.addScaledVector(s[6],.743125*r*r-.247708),e.addScaledVector(s[7],.858086*i*r),e.addScaledVector(s[8],.429043*(i*i-n*n)),e}add(t){for(let e=0;e<9;e++)this.coefficients[e].add(t.coefficients[e]);return this}addScaledSH(t,e){for(let i=0;i<9;i++)this.coefficients[i].addScaledVector(t.coefficients[i],e);return this}scale(t){for(let e=0;e<9;e++)this.coefficients[e].multiplyScalar(t);return this}lerp(t,e){for(let i=0;i<9;i++)this.coefficients[i].lerp(t.coefficients[i],e);return this}equals(t){for(let e=0;e<9;e++)if(!this.coefficients[e].equals(t.coefficients[e]))return!1;return!0}copy(t){return this.set(t.coefficients)}clone(){return(new this.constructor).copy(this)}fromArray(t,e=0){const i=this.coefficients;for(let n=0;n<9;n++)i[n].fromArray(t,e+3*n);return this}toArray(t=[],e=0){const i=this.coefficients;for(let n=0;n<9;n++)i[n].toArray(t,e+3*n);return t}static getBasisAt(t,e){const i=t.x,n=t.y,r=t.z;e[0]=.282095,e[1]=.488603*n,e[2]=.488603*r,e[3]=.488603*i,e[4]=1.092548*i*n,e[5]=1.092548*n*r,e[6]=.315392*(3*r*r-1),e[7]=1.092548*i*r,e[8]=.546274*(i*i-n*n)}}class Uc extends _c{constructor(t=new zc,e=1){super(void 0,e),this.isLightProbe=!0,this.sh=t}copy(t){return super.copy(t),this.sh.copy(t.sh),this}fromJSON(t){return this.intensity=t.intensity,this.sh.fromArray(t.sh),this}toJSON(t){const e=super.toJSON(t);return e.object.sh=this.sh.toArray(),e}}class Bc extends mc{constructor(t){super(t),this.textures={}}load(t,e,i,n){const r=this,s=new vc(r.manager);s.setPath(r.path),s.setRequestHeader(r.requestHeader),s.setWithCredentials(r.withCredentials),s.load(t,(function(i){try{e(r.parse(JSON.parse(i)))}catch(e){n?n(e):console.error(e),r.manager.itemError(t)}}),i,n)}parse(t){const e=this.textures;function i(t){return void 0===e[t]&&console.warn("THREE.MaterialLoader: Undefined texture",t),e[t]}const n=Bc.createMaterialFromType(t.type);if(void 0!==t.uuid&&(n.uuid=t.uuid),void 0!==t.name&&(n.name=t.name),void 0!==t.color&&void 0!==n.color&&n.color.setHex(t.color),void 0!==t.roughness&&(n.roughness=t.roughness),void 0!==t.metalness&&(n.metalness=t.metalness),void 0!==t.sheen&&(n.sheen=t.sheen),void 0!==t.sheenColor&&(n.sheenColor=(new qt).setHex(t.sheenColor)),void 0!==t.sheenRoughness&&(n.sheenRoughness=t.sheenRoughness),void 0!==t.emissive&&void 0!==n.emissive&&n.emissive.setHex(t.emissive),void 0!==t.specular&&void 0!==n.specular&&n.specular.setHex(t.specular),void 0!==t.specularIntensity&&(n.specularIntensity=t.specularIntensity),void 0!==t.specularColor&&void 0!==n.specularColor&&n.specularColor.setHex(t.specularColor),void 0!==t.shininess&&(n.shininess=t.shininess),void 0!==t.clearcoat&&(n.clearcoat=t.clearcoat),void 0!==t.clearcoatRoughness&&(n.clearcoatRoughness=t.clearcoatRoughness),void 0!==t.iridescence&&(n.iridescence=t.iridescence),void 0!==t.iridescenceIOR&&(n.iridescenceIOR=t.iridescenceIOR),void 0!==t.iridescenceThicknessRange&&(n.iridescenceThicknessRange=t.iridescenceThicknessRange),void 0!==t.transmission&&(n.transmission=t.transmission),void 0!==t.thickness&&(n.thickness=t.thickness),void 0!==t.attenuationDistance&&(n.attenuationDistance=t.attenuationDistance),void 0!==t.attenuationColor&&void 0!==n.attenuationColor&&n.attenuationColor.setHex(t.attenuationColor),void 0!==t.fog&&(n.fog=t.fog),void 0!==t.flatShading&&(n.flatShading=t.flatShading),void 0!==t.blending&&(n.blending=t.blending),void 0!==t.combine&&(n.combine=t.combine),void 0!==t.side&&(n.side=t.side),void 0!==t.shadowSide&&(n.shadowSide=t.shadowSide),void 0!==t.opacity&&(n.opacity=t.opacity),void 0!==t.transparent&&(n.transparent=t.transparent),void 0!==t.alphaTest&&(n.alphaTest=t.alphaTest),void 0!==t.depthTest&&(n.depthTest=t.depthTest),void 0!==t.depthWrite&&(n.depthWrite=t.depthWrite),void 0!==t.colorWrite&&(n.colorWrite=t.colorWrite),void 0!==t.stencilWrite&&(n.stencilWrite=t.stencilWrite),void 0!==t.stencilWriteMask&&(n.stencilWriteMask=t.stencilWriteMask),void 0!==t.stencilFunc&&(n.stencilFunc=t.stencilFunc),void 0!==t.stencilRef&&(n.stencilRef=t.stencilRef),void 0!==t.stencilFuncMask&&(n.stencilFuncMask=t.stencilFuncMask),void 0!==t.stencilFail&&(n.stencilFail=t.stencilFail),void 0!==t.stencilZFail&&(n.stencilZFail=t.stencilZFail),void 0!==t.stencilZPass&&(n.stencilZPass=t.stencilZPass),void 0!==t.wireframe&&(n.wireframe=t.wireframe),void 0!==t.wireframeLinewidth&&(n.wireframeLinewidth=t.wireframeLinewidth),void 0!==t.wireframeLinecap&&(n.wireframeLinecap=t.wireframeLinecap),void 0!==t.wireframeLinejoin&&(n.wireframeLinejoin=t.wireframeLinejoin),void 0!==t.rotation&&(n.rotation=t.rotation),1!==t.linewidth&&(n.linewidth=t.linewidth),void 0!==t.dashSize&&(n.dashSize=t.dashSize),void 0!==t.gapSize&&(n.gapSize=t.gapSize),void 0!==t.scale&&(n.scale=t.scale),void 0!==t.polygonOffset&&(n.polygonOffset=t.polygonOffset),void 0!==t.polygonOffsetFactor&&(n.polygonOffsetFactor=t.polygonOffsetFactor),void 0!==t.polygonOffsetUnits&&(n.polygonOffsetUnits=t.polygonOffsetUnits),void 0!==t.dithering&&(n.dithering=t.dithering),void 0!==t.alphaToCoverage&&(n.alphaToCoverage=t.alphaToCoverage),void 0!==t.premultipliedAlpha&&(n.premultipliedAlpha=t.premultipliedAlpha),void 0!==t.visible&&(n.visible=t.visible),void 0!==t.toneMapped&&(n.toneMapped=t.toneMapped),void 0!==t.userData&&(n.userData=t.userData),void 0!==t.vertexColors&&("number"==typeof t.vertexColors?n.vertexColors=t.vertexColors>0:n.vertexColors=t.vertexColors),void 0!==t.uniforms)for(const e in t.uniforms){const r=t.uniforms[e];switch(n.uniforms[e]={},r.type){case"t":n.uniforms[e].value=i(r.value);break;case"c":n.uniforms[e].value=(new qt).setHex(r.value);break;case"v2":n.uniforms[e].value=(new Lt).fromArray(r.value);break;case"v3":n.uniforms[e].value=(new re).fromArray(r.value);break;case"v4":n.uniforms[e].value=(new Qt).fromArray(r.value);break;case"m3":n.uniforms[e].value=(new Rt).fromArray(r.value);break;case"m4":n.uniforms[e].value=(new Ne).fromArray(r.value);break;default:n.uniforms[e].value=r.value}}if(void 0!==t.defines&&(n.defines=t.defines),void 0!==t.vertexShader&&(n.vertexShader=t.vertexShader),void 0!==t.fragmentShader&&(n.fragmentShader=t.fragmentShader),void 0!==t.glslVersion&&(n.glslVersion=t.glslVersion),void 0!==t.extensions)for(const e in t.extensions)n.extensions[e]=t.extensions[e];if(void 0!==t.size&&(n.size=t.size),void 0!==t.sizeAttenuation&&(n.sizeAttenuation=t.sizeAttenuation),void 0!==t.map&&(n.map=i(t.map)),void 0!==t.matcap&&(n.matcap=i(t.matcap)),void 0!==t.alphaMap&&(n.alphaMap=i(t.alphaMap)),void 0!==t.bumpMap&&(n.bumpMap=i(t.bumpMap)),void 0!==t.bumpScale&&(n.bumpScale=t.bumpScale),void 0!==t.normalMap&&(n.normalMap=i(t.normalMap)),void 0!==t.normalMapType&&(n.normalMapType=t.normalMapType),void 0!==t.normalScale){let e=t.normalScale;!1===Array.isArray(e)&&(e=[e,e]),n.normalScale=(new Lt).fromArray(e)}return void 0!==t.displacementMap&&(n.displacementMap=i(t.displacementMap)),void 0!==t.displacementScale&&(n.displacementScale=t.displacementScale),void 0!==t.displacementBias&&(n.displacementBias=t.displacementBias),void 0!==t.roughnessMap&&(n.roughnessMap=i(t.roughnessMap)),void 0!==t.metalnessMap&&(n.metalnessMap=i(t.metalnessMap)),void 0!==t.emissiveMap&&(n.emissiveMap=i(t.emissiveMap)),void 0!==t.emissiveIntensity&&(n.emissiveIntensity=t.emissiveIntensity),void 0!==t.specularMap&&(n.specularMap=i(t.specularMap)),void 0!==t.specularIntensityMap&&(n.specularIntensityMap=i(t.specularIntensityMap)),void 0!==t.specularColorMap&&(n.specularColorMap=i(t.specularColorMap)),void 0!==t.envMap&&(n.envMap=i(t.envMap)),void 0!==t.envMapIntensity&&(n.envMapIntensity=t.envMapIntensity),void 0!==t.reflectivity&&(n.reflectivity=t.reflectivity),void 0!==t.refractionRatio&&(n.refractionRatio=t.refractionRatio),void 0!==t.lightMap&&(n.lightMap=i(t.lightMap)),void 0!==t.lightMapIntensity&&(n.lightMapIntensity=t.lightMapIntensity),void 0!==t.aoMap&&(n.aoMap=i(t.aoMap)),void 0!==t.aoMapIntensity&&(n.aoMapIntensity=t.aoMapIntensity),void 0!==t.gradientMap&&(n.gradientMap=i(t.gradientMap)),void 0!==t.clearcoatMap&&(n.clearcoatMap=i(t.clearcoatMap)),void 0!==t.clearcoatRoughnessMap&&(n.clearcoatRoughnessMap=i(t.clearcoatRoughnessMap)),void 0!==t.clearcoatNormalMap&&(n.clearcoatNormalMap=i(t.clearcoatNormalMap)),void 0!==t.clearcoatNormalScale&&(n.clearcoatNormalScale=(new Lt).fromArray(t.clearcoatNormalScale)),void 0!==t.iridescenceMap&&(n.iridescenceMap=i(t.iridescenceMap)),void 0!==t.iridescenceThicknessMap&&(n.iridescenceThicknessMap=i(t.iridescenceThicknessMap)),void 0!==t.transmissionMap&&(n.transmissionMap=i(t.transmissionMap)),void 0!==t.thicknessMap&&(n.thicknessMap=i(t.thicknessMap)),void 0!==t.sheenColorMap&&(n.sheenColorMap=i(t.sheenColorMap)),void 0!==t.sheenRoughnessMap&&(n.sheenRoughnessMap=i(t.sheenRoughnessMap)),n}setTextures(t){return this.textures=t,this}static createMaterialFromType(t){return new{ShadowMaterial:Nl,SpriteMaterial:la,RawShaderMaterial:Ol,ShaderMaterial:sn,PointsMaterial:io,MeshPhysicalMaterial:Ul,MeshStandardMaterial:zl,MeshPhongMaterial:Bl,MeshToonMaterial:Fl,MeshNormalMaterial:kl,MeshLambertMaterial:Gl,MeshDepthMaterial:Us,MeshDistanceMaterial:Bs,MeshBasicMaterial:_i,MeshMatcapMaterial:Vl,LineDashedMaterial:Hl,LineBasicMaterial:ja,Material:xi}[t]}}class Fc{static decodeText(t){if("undefined"!=typeof TextDecoder)return(new TextDecoder).decode(t);let e="";for(let i=0,n=t.length;i0){this.source.connect(this.filters[0]);for(let t=1,e=this.filters.length;t0){this.source.disconnect(this.filters[0]);for(let t=1,e=this.filters.length;t0&&this._mixBufferRegionAdditive(i,n,this._addIndex*e,1,e);for(let t=e,r=e+e;t!==r;++t)if(i[t]!==i[t+e]){a.setValue(i,n);break}}saveOriginalState(){const t=this.binding,e=this.buffer,i=this.valueSize,n=i*this._origIndex;t.getValue(e,n);for(let t=i,r=n;t!==r;++t)e[t]=e[n+t%i];this._setIdentity(),this.cumulativeWeight=0,this.cumulativeWeightAdditive=0}restoreOriginalState(){const t=3*this.valueSize;this.binding.setValue(this.buffer,t)}_setAdditiveIdentityNumeric(){const t=this._addIndex*this.valueSize,e=t+this.valueSize;for(let i=t;i=.5)for(let n=0;n!==r;++n)t[e+n]=t[i+n]}_slerp(t,e,i,n){ne.slerpFlat(t,e,t,e,t,i,n)}_slerpAdditive(t,e,i,n,r){const s=this._workIndex*r;ne.multiplyQuaternionsFlat(t,s,t,e,t,i),ne.slerpFlat(t,e,t,e,t,s,n)}_lerp(t,e,i,n,r){const s=1-n;for(let a=0;a!==r;++a){const r=e+a;t[r]=t[r]*s+t[i+a]*n}}_lerpAdditive(t,e,i,n,r){for(let s=0;s!==r;++s){const r=e+s;t[r]=t[r]+t[i+s]*n}}}const lh="\\[\\]\\.:\\/",ch=new RegExp("[\\[\\]\\.:\\/]","g"),hh="[^\\[\\]\\.:\\/]",uh="[^"+lh.replace("\\.","")+"]",dh=new RegExp("^"+/((?:WC+[\/:])*)/.source.replace("WC",hh)+/(WCOD+)?/.source.replace("WCOD",uh)+/(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace("WC",hh)+/\.(WC+)(?:\[(.+)\])?/.source.replace("WC",hh)+"$"),ph=["material","materials","bones","map"];class mh{constructor(t,e,i){this.path=e,this.parsedPath=i||mh.parseTrackName(e),this.node=mh.findNode(t,this.parsedPath.nodeName)||t,this.rootNode=t,this.getValue=this._getValue_unbound,this.setValue=this._setValue_unbound}static create(t,e,i){return t&&t.isAnimationObjectGroup?new mh.Composite(t,e,i):new mh(t,e,i)}static sanitizeNodeName(t){return t.replace(/\s/g,"_").replace(ch,"")}static parseTrackName(t){const e=dh.exec(t);if(null===e)throw new Error("PropertyBinding: Cannot parse trackName: "+t);const i={nodeName:e[2],objectName:e[3],objectIndex:e[4],propertyName:e[5],propertyIndex:e[6]},n=i.nodeName&&i.nodeName.lastIndexOf(".");if(void 0!==n&&-1!==n){const t=i.nodeName.substring(n+1);-1!==ph.indexOf(t)&&(i.nodeName=i.nodeName.substring(0,n),i.objectName=t)}if(null===i.propertyName||0===i.propertyName.length)throw new Error("PropertyBinding: can not parse propertyName from trackName: "+t);return i}static findNode(t,e){if(void 0===e||""===e||"."===e||-1===e||e===t.name||e===t.uuid)return t;if(t.skeleton){const i=t.skeleton.getBoneByName(e);if(void 0!==i)return i}if(t.children){const i=function(t){for(let n=0;n0){const t=this._interpolants,e=this._propertyBindings;if(this.blendMode===st)for(let i=0,n=t.length;i!==n;++i)t[i].evaluate(s),e[i].accumulateAdditive(a);else for(let i=0,r=t.length;i!==r;++i)t[i].evaluate(s),e[i].accumulate(n,a)}}_updateWeight(t){let e=0;if(this.enabled){e=this.weight;const i=this._weightInterpolant;if(null!==i){const n=i.evaluate(t)[0];e*=n,t>i.parameterPositions[1]&&(this.stopFading(),0===n&&(this.enabled=!1))}}return this._effectiveWeight=e,e}_updateTimeScale(t){let e=0;if(!this.paused){e=this.timeScale;const i=this._timeScaleInterpolant;if(null!==i){e*=i.evaluate(t)[0],t>i.parameterPositions[1]&&(this.stopWarping(),0===e?this.paused=!0:this.timeScale=e)}}return this._effectiveTimeScale=e,e}_updateTime(t){const e=this._clip.duration,i=this.loop;let n=this.time+t,r=this._loopCount;const s=2202===i;if(0===t)return-1===r?n:s&&1==(1&r)?e-n:n;if(2200===i){-1===r&&(this._loopCount=0,this._setEndings(!0,!0,!1));t:{if(n>=e)n=e;else{if(!(n<0)){this.time=n;break t}n=0}this.clampWhenFinished?this.paused=!0:this.enabled=!1,this.time=n,this._mixer.dispatchEvent({type:"finished",action:this,direction:t<0?-1:1})}}else{if(-1===r&&(t>=0?(r=0,this._setEndings(!0,0===this.repetitions,s)):this._setEndings(0===this.repetitions,!0,s)),n>=e||n<0){const i=Math.floor(n/e);n-=e*i,r+=Math.abs(i);const a=this.repetitions-r;if(a<=0)this.clampWhenFinished?this.paused=!0:this.enabled=!1,n=t>0?e:0,this.time=n,this._mixer.dispatchEvent({type:"finished",action:this,direction:t>0?1:-1});else{if(1===a){const e=t<0;this._setEndings(e,!e,s)}else this._setEndings(!1,!1,s);this._loopCount=r,this.time=n,this._mixer.dispatchEvent({type:"loop",action:this,loopDelta:i})}}else this.time=n;if(s&&1==(1&r))return e-n}return n}_setEndings(t,e,i){const n=this._interpolantSettings;i?(n.endingStart=it,n.endingEnd=it):(n.endingStart=t?this.zeroSlopeAtStart?it:et:nt,n.endingEnd=e?this.zeroSlopeAtEnd?it:et:nt)}_scheduleFading(t,e,i){const n=this._mixer,r=n.time;let s=this._weightInterpolant;null===s&&(s=n._lendControlInterpolant(),this._weightInterpolant=s);const a=s.parameterPositions,o=s.sampleValues;return a[0]=r,o[0]=e,a[1]=r+t,o[1]=i,this}}const gh=new Float32Array(1);class vh{constructor(t){this.value=t}clone(){return new vh(void 0===this.value.clone?this.value:this.value.clone())}}let xh=0;function _h(t,e){return t.distance-e.distance}function yh(t,e,i,n){if(t.layers.test(e.layers)&&t.raycast(e,i),!0===n){const n=t.children;for(let t=0,r=n.length;t>-e-14,n[256|t]=1024>>-e-14|32768,r[t]=-e-1,r[256|t]=-e-1):e<=15?(n[t]=e+15<<10,n[256|t]=e+15<<10|32768,r[t]=13,r[256|t]=13):e<128?(n[t]=31744,n[256|t]=64512,r[t]=24,r[256|t]=24):(n[t]=31744,n[256|t]=64512,r[t]=13,r[256|t]=13)}const s=new Uint32Array(2048),a=new Uint32Array(64),o=new Uint32Array(64);for(let t=1;t<1024;++t){let e=t<<13,i=0;for(;0==(8388608&e);)e<<=1,i-=8388608;e&=-8388609,i+=947912704,s[t]=e|i}for(let t=1024;t<2048;++t)s[t]=939524096+(t-1024<<13);for(let t=1;t<31;++t)a[t]=t<<23;a[31]=1199570944,a[32]=2147483648;for(let t=33;t<63;++t)a[t]=2147483648+(t-32<<23);a[63]=3347054592;for(let t=1;t<64;++t)32!==t&&(o[t]=1024);return{floatView:e,uint32View:i,baseTable:n,shiftTable:r,mantissaTable:s,exponentTable:a,offsetTable:o}}var Wh=Object.freeze({__proto__:null,toHalfFloat:function(t){Math.abs(t)>65504&&console.warn("THREE.DataUtils.toHalfFloat(): Value out of range."),t=yt(t,-65504,65504),Vh.floatView[0]=t;const e=Vh.uint32View[0],i=e>>23&511;return Vh.baseTable[i]+((8388607&e)>>Vh.shiftTable[i])},fromHalfFloat:function(t){const e=t>>10;return Vh.uint32View[0]=Vh.mantissaTable[Vh.offsetTable[e]+(1023&t)]+Vh.exponentTable[e],Vh.floatView[0]}});"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("register",{detail:{revision:e}})),"undefined"!=typeof window&&(window.__THREE__?console.warn("WARNING: Multiple instances of Three.js being imported."):window.__THREE__=e),t.ACESFilmicToneMapping=4,t.AddEquation=i,t.AddOperation=2,t.AdditiveAnimationBlendMode=st,t.AdditiveBlending=2,t.AlphaFormat=1021,t.AlwaysDepth=1,t.AlwaysStencilFunc=519,t.AmbientLight=Nc,t.AmbientLightProbe=class extends Uc{constructor(t,e=1){super(void 0,e),this.isAmbientLightProbe=!0;const i=(new qt).set(t);this.sh.coefficients[0].set(i.r,i.g,i.b).multiplyScalar(2*Math.sqrt(Math.PI))}},t.AnimationClip=cc,t.AnimationLoader=class extends mc{constructor(t){super(t)}load(t,e,i,n){const r=this,s=new vc(this.manager);s.setPath(this.path),s.setRequestHeader(this.requestHeader),s.setWithCredentials(this.withCredentials),s.load(t,(function(i){try{e(r.parse(JSON.parse(i)))}catch(e){n?n(e):console.error(e),r.manager.itemError(t)}}),i,n)}parse(t){const e=[];for(let i=0;i=0;--e)t[e].stop();return this}update(t){t*=this.timeScale;const e=this._actions,i=this._nActiveActions,n=this.time+=t,r=Math.sign(t),s=this._accuIndex^=1;for(let a=0;a!==i;++a){e[a]._update(n,t,r,s)}const a=this._bindings,o=this._nActiveBindings;for(let t=0;t!==o;++t)a[t].apply(s);return this}setTime(t){this.time=0;for(let t=0;t=r){const s=r++,c=t[s];e[c.uuid]=l,t[l]=c,e[o]=s,t[s]=a;for(let t=0,e=n;t!==e;++t){const e=i[t],n=e[s],r=e[l];e[l]=n,e[s]=r}}}this.nCachedObjects_=r}uncache(){const t=this._objects,e=this._indicesByUUID,i=this._bindings,n=i.length;let r=this.nCachedObjects_,s=t.length;for(let a=0,o=arguments.length;a!==o;++a){const o=arguments[a].uuid,l=e[o];if(void 0!==l)if(delete e[o],l0&&(e[a.uuid]=l),t[l]=a,t.pop();for(let t=0,e=n;t!==e;++t){const e=i[t];e[l]=e[r],e.pop()}}}this.nCachedObjects_=r}subscribe_(t,e){const i=this._bindingsIndicesByPath;let n=i[t];const r=this._bindings;if(void 0!==n)return r[n];const s=this._paths,a=this._parsedPaths,o=this._objects,l=o.length,c=this.nCachedObjects_,h=new Array(l);n=r.length,i[t]=n,s.push(t),a.push(e),r.push(h);for(let i=c,n=o.length;i!==n;++i){const n=o[i];h[i]=new mh(n,t,e)}return h}unsubscribe_(t){const e=this._bindingsIndicesByPath,i=e[t];if(void 0!==i){const n=this._paths,r=this._parsedPaths,s=this._bindings,a=s.length-1,o=s[a];e[t[a]]=i,s[i]=o,s.pop(),r[i]=r[a],r.pop(),n[i]=n[a],n.pop()}}},t.AnimationUtils=Jl,t.ArcCurve=po,t.ArrayCamera=Ws,t.ArrowHelper=class extends si{constructor(t=new re(0,0,1),e=new re(0,0,0),i=1,n=16776960,r=.2*i,s=.2*r){super(),this.type="ArrowHelper",void 0===kh&&(kh=new Di,kh.setAttribute("position",new Ti([0,0,0,0,1,0],3)),Gh=new zo(0,.5,1,5,1),Gh.translate(0,-.5,0)),this.position.copy(e),this.line=new Ka(kh,new ja({color:n,toneMapped:!1})),this.line.matrixAutoUpdate=!1,this.add(this.line),this.cone=new Ki(Gh,new _i({color:n,toneMapped:!1})),this.cone.matrixAutoUpdate=!1,this.add(this.cone),this.setDirection(t),this.setLength(i,r,s)}setDirection(t){if(t.y>.99999)this.quaternion.set(0,0,0,1);else if(t.y<-.99999)this.quaternion.set(1,0,0,0);else{Fh.set(t.z,0,-t.x).normalize();const e=Math.acos(t.y);this.quaternion.setFromAxisAngle(Fh,e)}}setLength(t,e=.2*t,i=.2*e){this.line.scale.set(1,Math.max(1e-4,t-e),1),this.line.updateMatrix(),this.cone.scale.set(i,e,i),this.cone.position.y=t,this.cone.updateMatrix()}setColor(t){this.line.material.color.set(t),this.cone.material.color.set(t)}copy(t){return super.copy(t,!1),this.line.copy(t.line),this.cone.copy(t.cone),this}dispose(){this.line.geometry.dispose(),this.line.material.dispose(),this.cone.geometry.dispose(),this.cone.material.dispose()}},t.Audio=ih,t.AudioAnalyser=class{constructor(t,e=2048){this.analyser=t.context.createAnalyser(),this.analyser.fftSize=e,this.data=new Uint8Array(this.analyser.frequencyBinCount),t.getOutput().connect(this.analyser)}getFrequencyData(){return this.analyser.getByteFrequencyData(this.data),this.data}getAverageFrequency(){let t=0;const e=this.getFrequencyData();for(let i=0;ithis.max.x||t.ythis.max.y)}containsBox(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y}getParameter(t,e){return e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y))}intersectsBox(t){return!(t.max.xthis.max.x||t.max.ythis.max.y)}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return Mh.copy(t).clamp(this.min,this.max).sub(t).length()}intersect(t){return this.min.max(t.min),this.max.min(t.max),this}union(t){return this.min.min(t.min),this.max.max(t.max),this}translate(t){return this.min.add(t),this.max.add(t),this}equals(t){return t.min.equals(this.min)&&t.max.equals(this.max)}},t.Box3=oe,t.Box3Helper=class extends to{constructor(t,e=16776960){const i=new Uint16Array([0,1,1,2,2,3,3,0,4,5,5,6,6,7,7,4,0,4,1,5,2,6,3,7]),n=new Di;n.setIndex(new bi(i,1)),n.setAttribute("position",new Ti([1,1,1,-1,1,1,-1,-1,1,1,-1,1,1,1,-1,-1,1,-1,-1,-1,-1,1,-1,-1],3)),super(n,new ja({color:e,toneMapped:!1})),this.box=t,this.type="Box3Helper",this.geometry.computeBoundingSphere()}updateMatrixWorld(t){const e=this.box;e.isEmpty()||(e.getCenter(this.position),e.getSize(this.scale),this.scale.multiplyScalar(.5),super.updateMatrixWorld(t))}dispose(){this.geometry.dispose(),this.material.dispose()}},t.BoxBufferGeometry=class extends Qi{constructor(t,e,i,n,r,s){console.warn("THREE.BoxBufferGeometry has been renamed to THREE.BoxGeometry."),super(t,e,i,n,r,s)}},t.BoxGeometry=Qi,t.BoxHelper=class extends to{constructor(t,e=16776960){const i=new Uint16Array([0,1,1,2,2,3,3,0,4,5,5,6,6,7,7,4,0,4,1,5,2,6,3,7]),n=new Float32Array(24),r=new Di;r.setIndex(new bi(i,1)),r.setAttribute("position",new bi(n,3)),super(r,new ja({color:e,toneMapped:!1})),this.object=t,this.type="BoxHelper",this.matrixAutoUpdate=!1,this.update()}update(t){if(void 0!==t&&console.warn("THREE.BoxHelper: .update() has no longer arguments."),void 0!==this.object&&Bh.setFromObject(this.object),Bh.isEmpty())return;const e=Bh.min,i=Bh.max,n=this.geometry.attributes.position,r=n.array;r[0]=i.x,r[1]=i.y,r[2]=i.z,r[3]=e.x,r[4]=i.y,r[5]=i.z,r[6]=e.x,r[7]=e.y,r[8]=i.z,r[9]=i.x,r[10]=e.y,r[11]=i.z,r[12]=i.x,r[13]=i.y,r[14]=e.z,r[15]=e.x,r[16]=i.y,r[17]=e.z,r[18]=e.x,r[19]=e.y,r[20]=e.z,r[21]=i.x,r[22]=e.y,r[23]=e.z,n.needsUpdate=!0,this.geometry.computeBoundingSphere()}setFromObject(t){return this.object=t,this.update(),this}copy(t,e){return super.copy(t,e),this.object=t.object,this}dispose(){this.geometry.dispose(),this.material.dispose()}},t.BufferAttribute=bi,t.BufferGeometry=Di,t.BufferGeometryLoader=Gc,t.ByteType=1010,t.Cache=uc,t.Camera=an,t.CameraHelper=class extends to{constructor(t){const e=new Di,i=new ja({color:16777215,vertexColors:!0,toneMapped:!1}),n=[],r=[],s={};function a(t,e){o(t),o(e)}function o(t){n.push(0,0,0),r.push(0,0,0),void 0===s[t]&&(s[t]=[]),s[t].push(n.length/3-1)}a("n1","n2"),a("n2","n4"),a("n4","n3"),a("n3","n1"),a("f1","f2"),a("f2","f4"),a("f4","f3"),a("f3","f1"),a("n1","f1"),a("n2","f2"),a("n3","f3"),a("n4","f4"),a("p","n1"),a("p","n2"),a("p","n3"),a("p","n4"),a("u1","u2"),a("u2","u3"),a("u3","u1"),a("c","t"),a("p","c"),a("cn1","cn2"),a("cn3","cn4"),a("cf1","cf2"),a("cf3","cf4"),e.setAttribute("position",new Ti(n,3)),e.setAttribute("color",new Ti(r,3)),super(e,i),this.type="CameraHelper",this.camera=t,this.camera.updateProjectionMatrix&&this.camera.updateProjectionMatrix(),this.matrix=t.matrixWorld,this.matrixAutoUpdate=!1,this.pointMap=s,this.update();const l=new qt(16755200),c=new qt(16711680),h=new qt(43775),u=new qt(16777215),d=new qt(3355443);this.setColors(l,c,h,u,d)}setColors(t,e,i,n,r){const s=this.geometry.getAttribute("color");s.setXYZ(0,t.r,t.g,t.b),s.setXYZ(1,t.r,t.g,t.b),s.setXYZ(2,t.r,t.g,t.b),s.setXYZ(3,t.r,t.g,t.b),s.setXYZ(4,t.r,t.g,t.b),s.setXYZ(5,t.r,t.g,t.b),s.setXYZ(6,t.r,t.g,t.b),s.setXYZ(7,t.r,t.g,t.b),s.setXYZ(8,t.r,t.g,t.b),s.setXYZ(9,t.r,t.g,t.b),s.setXYZ(10,t.r,t.g,t.b),s.setXYZ(11,t.r,t.g,t.b),s.setXYZ(12,t.r,t.g,t.b),s.setXYZ(13,t.r,t.g,t.b),s.setXYZ(14,t.r,t.g,t.b),s.setXYZ(15,t.r,t.g,t.b),s.setXYZ(16,t.r,t.g,t.b),s.setXYZ(17,t.r,t.g,t.b),s.setXYZ(18,t.r,t.g,t.b),s.setXYZ(19,t.r,t.g,t.b),s.setXYZ(20,t.r,t.g,t.b),s.setXYZ(21,t.r,t.g,t.b),s.setXYZ(22,t.r,t.g,t.b),s.setXYZ(23,t.r,t.g,t.b),s.setXYZ(24,e.r,e.g,e.b),s.setXYZ(25,e.r,e.g,e.b),s.setXYZ(26,e.r,e.g,e.b),s.setXYZ(27,e.r,e.g,e.b),s.setXYZ(28,e.r,e.g,e.b),s.setXYZ(29,e.r,e.g,e.b),s.setXYZ(30,e.r,e.g,e.b),s.setXYZ(31,e.r,e.g,e.b),s.setXYZ(32,i.r,i.g,i.b),s.setXYZ(33,i.r,i.g,i.b),s.setXYZ(34,i.r,i.g,i.b),s.setXYZ(35,i.r,i.g,i.b),s.setXYZ(36,i.r,i.g,i.b),s.setXYZ(37,i.r,i.g,i.b),s.setXYZ(38,n.r,n.g,n.b),s.setXYZ(39,n.r,n.g,n.b),s.setXYZ(40,r.r,r.g,r.b),s.setXYZ(41,r.r,r.g,r.b),s.setXYZ(42,r.r,r.g,r.b),s.setXYZ(43,r.r,r.g,r.b),s.setXYZ(44,r.r,r.g,r.b),s.setXYZ(45,r.r,r.g,r.b),s.setXYZ(46,r.r,r.g,r.b),s.setXYZ(47,r.r,r.g,r.b),s.setXYZ(48,r.r,r.g,r.b),s.setXYZ(49,r.r,r.g,r.b),s.needsUpdate=!0}update(){const t=this.geometry,e=this.pointMap;zh.projectionMatrixInverse.copy(this.camera.projectionMatrixInverse),Uh("c",e,t,zh,0,0,-1),Uh("t",e,t,zh,0,0,1),Uh("n1",e,t,zh,-1,-1,-1),Uh("n2",e,t,zh,1,-1,-1),Uh("n3",e,t,zh,-1,1,-1),Uh("n4",e,t,zh,1,1,-1),Uh("f1",e,t,zh,-1,-1,1),Uh("f2",e,t,zh,1,-1,1),Uh("f3",e,t,zh,-1,1,1),Uh("f4",e,t,zh,1,1,1),Uh("u1",e,t,zh,.7,1.1,-1),Uh("u2",e,t,zh,-.7,1.1,-1),Uh("u3",e,t,zh,0,2,-1),Uh("cf1",e,t,zh,-1,0,1),Uh("cf2",e,t,zh,1,0,1),Uh("cf3",e,t,zh,0,-1,1),Uh("cf4",e,t,zh,0,1,1),Uh("cn1",e,t,zh,-1,0,-1),Uh("cn2",e,t,zh,1,0,-1),Uh("cn3",e,t,zh,0,-1,-1),Uh("cn4",e,t,zh,0,1,-1),t.getAttribute("position").needsUpdate=!0}dispose(){this.geometry.dispose(),this.material.dispose()}},t.CanvasTexture=class extends $t{constructor(t,e,i,n,r,s,a,o,l){super(t,e,i,n,r,s,a,o,l),this.isCanvasTexture=!0,this.needsUpdate=!0}},t.CapsuleBufferGeometry=class extends No{constructor(t,e,i,n){console.warn("THREE.CapsuleBufferGeometry has been renamed to THREE.CapsuleGeometry."),super(t,e,i,n)}},t.CapsuleGeometry=No,t.CatmullRomCurve3=_o,t.CineonToneMapping=3,t.CircleBufferGeometry=class extends Oo{constructor(t,e,i,n){console.warn("THREE.CircleBufferGeometry has been renamed to THREE.CircleGeometry."),super(t,e,i,n)}},t.CircleGeometry=Oo,t.ClampToEdgeWrapping=h,t.Clock=Jc,t.Color=qt,t.ColorKeyframeTrack=nc,t.ColorManagement=Ft,t.CompressedArrayTexture=class extends co{constructor(t,e,i,n,r,s){super(t,e,i,r,s),this.isCompressedArrayTexture=!0,this.image.depth=n,this.wrapR=h}},t.CompressedTexture=co,t.CompressedTextureLoader=class extends mc{constructor(t){super(t)}load(t,e,i,n){const r=this,s=[],a=new co,o=new vc(this.manager);o.setPath(this.path),o.setResponseType("arraybuffer"),o.setRequestHeader(this.requestHeader),o.setWithCredentials(r.withCredentials);let l=0;function c(c){o.load(t[c],(function(t){const i=r.parse(t,!0);s[c]={width:i.width,height:i.height,format:i.format,mipmaps:i.mipmaps},l+=1,6===l&&(1===i.mipmapCount&&(a.minFilter=f),a.image=s,a.format=i.format,a.needsUpdate=!0,e&&e(a))}),i,n)}if(Array.isArray(t))for(let e=0,i=t.length;e0){const i=new dc(e);r=new xc(i),r.setCrossOrigin(this.crossOrigin);for(let e=0,i=t.length;e0){n=new xc(this.manager),n.setCrossOrigin(this.crossOrigin);for(let e=0,n=t.length;e1)for(let i=0;iNumber.EPSILON){if(l<0&&(i=e[s],o=-o,a=e[r],l=-l),t.ya.y)continue;if(t.y===i.y){if(t.x===i.x)return!0}else{const e=l*(t.x-i.x)-o*(t.y-i.y);if(0===e)return!0;if(e<0)continue;n=!n}}else{if(t.y!==i.y)continue;if(a.x<=t.x&&t.x<=i.x||i.x<=t.x&&t.x<=a.x)return!0}}return n}const i=vl.isClockWise,n=this.subPaths;if(0===n.length)return[];let r,s,a;const o=[];if(1===n.length)return s=n[0],a=new jo,a.curves=s.curves,o.push(a),o;let l=!i(n[0].getPoints());l=t?!l:l;const c=[],h=[];let u,d,p=[],m=0;h[m]=void 0,p[m]=[];for(let e=0,a=n.length;e1){let t=!1,i=0;for(let t=0,e=h.length;t0&&!1===t&&(p=c)}for(let t=0,e=h.length;t=t.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}},t.WebGL1Renderer=ea,t.WebGL3DRenderTarget=class extends te{constructor(t=1,e=1,i=1){super(t,e),this.isWebGL3DRenderTarget=!0,this.depth=i,this.texture=new ie(null,t,e,i),this.texture.isRenderTargetTexture=!0}},t.WebGLArrayRenderTarget=class extends te{constructor(t=1,e=1,i=1){super(t,e),this.isWebGLArrayRenderTarget=!0,this.depth=i,this.texture=new ee(null,t,e,i),this.texture.isRenderTargetTexture=!0}},t.WebGLCubeRenderTarget=un,t.WebGLMultipleRenderTargets=class extends te{constructor(t=1,e=1,i=1,n={}){super(t,e,n),this.isWebGLMultipleRenderTargets=!0;const r=this.texture;this.texture=[];for(let t=0;t>8&255]+ft[t>>16&255]+ft[t>>24&255]+"-"+ft[255&e]+ft[e>>8&255]+"-"+ft[e>>16&15|64]+ft[e>>24&255]+"-"+ft[63&i|128]+ft[i>>8&255]+"-"+ft[i>>16&255]+ft[i>>24&255]+ft[255&n]+ft[n>>8&255]+ft[n>>16&255]+ft[n>>24&255]).toLowerCase()}function yt(t,e,i){return Math.max(e,Math.min(i,t))}function Mt(t,e){return(t%e+e)%e}function bt(t,e,i){return(1-i)*t+i*e}function wt(t){return 0==(t&t-1)&&0!==t}function St(t){return Math.pow(2,Math.ceil(Math.log(t)/Math.LN2))}function Tt(t){return Math.pow(2,Math.floor(Math.log(t)/Math.LN2))}function At(t,e){switch(e.constructor){case Float32Array:return t;case Uint16Array:return t/65535;case Uint8Array:return t/255;case Int16Array:return Math.max(t/32767,-1);case Int8Array:return Math.max(t/127,-1);default:throw new Error("Invalid component type.")}}function Et(t,e){switch(e.constructor){case Float32Array:return t;case Uint16Array:return Math.round(65535*t);case Uint8Array:return Math.round(255*t);case Int16Array:return Math.round(32767*t);case Int8Array:return Math.round(127*t);default:throw new Error("Invalid component type.")}}var Ct=Object.freeze({__proto__:null,DEG2RAD:vt,RAD2DEG:xt,generateUUID:_t,clamp:yt,euclideanModulo:Mt,mapLinear:function(t,e,i,n,r){return n+(t-e)*(r-n)/(i-e)},inverseLerp:function(t,e,i){return t!==e?(i-t)/(e-t):0},lerp:bt,damp:function(t,e,i,n){return bt(t,e,1-Math.exp(-i*n))},pingpong:function(t,e=1){return e-Math.abs(Mt(t,2*e)-e)},smoothstep:function(t,e,i){return t<=e?0:t>=i?1:(t=(t-e)/(i-e))*t*(3-2*t)},smootherstep:function(t,e,i){return t<=e?0:t>=i?1:(t=(t-e)/(i-e))*t*t*(t*(6*t-15)+10)},randInt:function(t,e){return t+Math.floor(Math.random()*(e-t+1))},randFloat:function(t,e){return t+Math.random()*(e-t)},randFloatSpread:function(t){return t*(.5-Math.random())},seededRandom:function(t){void 0!==t&&(gt=t);let e=gt+=1831565813;return e=Math.imul(e^e>>>15,1|e),e^=e+Math.imul(e^e>>>7,61|e),((e^e>>>14)>>>0)/4294967296},degToRad:function(t){return t*vt},radToDeg:function(t){return t*xt},isPowerOfTwo:wt,ceilPowerOfTwo:St,floorPowerOfTwo:Tt,setQuaternionFromProperEuler:function(t,e,i,n,r){const s=Math.cos,a=Math.sin,o=s(i/2),l=a(i/2),c=s((e+n)/2),h=a((e+n)/2),u=s((e-n)/2),d=a((e-n)/2),p=s((n-e)/2),m=a((n-e)/2);switch(r){case"XYX":t.set(o*h,l*u,l*d,o*c);break;case"YZY":t.set(l*d,o*h,l*u,o*c);break;case"ZXZ":t.set(l*u,l*d,o*h,o*c);break;case"XZX":t.set(o*h,l*m,l*p,o*c);break;case"YXY":t.set(l*p,o*h,l*m,o*c);break;case"ZYZ":t.set(l*m,l*p,o*h,o*c);break;default:console.warn("THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: "+r)}},normalize:Et,denormalize:At});class Lt{constructor(t=0,e=0){Lt.prototype.isVector2=!0,this.x=t,this.y=e}get width(){return this.x}set width(t){this.x=t}get height(){return this.y}set height(t){this.y=t}set(t,e){return this.x=t,this.y=e,this}setScalar(t){return this.x=t,this.y=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y)}copy(t){return this.x=t.x,this.y=t.y,this}add(t){return this.x+=t.x,this.y+=t.y,this}addScalar(t){return this.x+=t,this.y+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this}subScalar(t){return this.x-=t,this.y-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this}multiply(t){return this.x*=t.x,this.y*=t.y,this}multiplyScalar(t){return this.x*=t,this.y*=t,this}divide(t){return this.x/=t.x,this.y/=t.y,this}divideScalar(t){return this.multiplyScalar(1/t)}applyMatrix3(t){const e=this.x,i=this.y,n=t.elements;return this.x=n[0]*e+n[3]*i+n[6],this.y=n[1]*e+n[4]*i+n[7],this}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this}clamp(t,e){return this.x=Math.max(t.x,Math.min(e.x,this.x)),this.y=Math.max(t.y,Math.min(e.y,this.y)),this}clampScalar(t,e){return this.x=Math.max(t,Math.min(e,this.x)),this.y=Math.max(t,Math.min(e,this.y)),this}clampLength(t,e){const i=this.length();return this.divideScalar(i||1).multiplyScalar(Math.max(t,Math.min(e,i)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this}roundToZero(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this}negate(){return this.x=-this.x,this.y=-this.y,this}dot(t){return this.x*t.x+this.y*t.y}cross(t){return this.x*t.y-this.y*t.x}lengthSq(){return this.x*this.x+this.y*this.y}length(){return Math.sqrt(this.x*this.x+this.y*this.y)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)}normalize(){return this.divideScalar(this.length()||1)}angle(){return Math.atan2(-this.y,-this.x)+Math.PI}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,i=this.y-t.y;return e*e+i*i}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this}lerpVectors(t,e,i){return this.x=t.x+(e.x-t.x)*i,this.y=t.y+(e.y-t.y)*i,this}equals(t){return t.x===this.x&&t.y===this.y}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this}rotateAround(t,e){const i=Math.cos(e),n=Math.sin(e),r=this.x-t.x,s=this.y-t.y;return this.x=r*i-s*n+t.x,this.y=r*n+s*i+t.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}}class Rt{constructor(){Rt.prototype.isMatrix3=!0,this.elements=[1,0,0,0,1,0,0,0,1]}set(t,e,i,n,r,s,a,o,l){const c=this.elements;return c[0]=t,c[1]=n,c[2]=a,c[3]=e,c[4]=r,c[5]=o,c[6]=i,c[7]=s,c[8]=l,this}identity(){return this.set(1,0,0,0,1,0,0,0,1),this}copy(t){const e=this.elements,i=t.elements;return e[0]=i[0],e[1]=i[1],e[2]=i[2],e[3]=i[3],e[4]=i[4],e[5]=i[5],e[6]=i[6],e[7]=i[7],e[8]=i[8],this}extractBasis(t,e,i){return t.setFromMatrix3Column(this,0),e.setFromMatrix3Column(this,1),i.setFromMatrix3Column(this,2),this}setFromMatrix4(t){const e=t.elements;return this.set(e[0],e[4],e[8],e[1],e[5],e[9],e[2],e[6],e[10]),this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const i=t.elements,n=e.elements,r=this.elements,s=i[0],a=i[3],o=i[6],l=i[1],c=i[4],h=i[7],u=i[2],d=i[5],p=i[8],m=n[0],f=n[3],g=n[6],v=n[1],x=n[4],_=n[7],y=n[2],M=n[5],b=n[8];return r[0]=s*m+a*v+o*y,r[3]=s*f+a*x+o*M,r[6]=s*g+a*_+o*b,r[1]=l*m+c*v+h*y,r[4]=l*f+c*x+h*M,r[7]=l*g+c*_+h*b,r[2]=u*m+d*v+p*y,r[5]=u*f+d*x+p*M,r[8]=u*g+d*_+p*b,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[3]*=t,e[6]*=t,e[1]*=t,e[4]*=t,e[7]*=t,e[2]*=t,e[5]*=t,e[8]*=t,this}determinant(){const t=this.elements,e=t[0],i=t[1],n=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8];return e*s*c-e*a*l-i*r*c+i*a*o+n*r*l-n*s*o}invert(){const t=this.elements,e=t[0],i=t[1],n=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8],h=c*s-a*l,u=a*o-c*r,d=l*r-s*o,p=e*h+i*u+n*d;if(0===p)return this.set(0,0,0,0,0,0,0,0,0);const m=1/p;return t[0]=h*m,t[1]=(n*l-c*i)*m,t[2]=(a*i-n*s)*m,t[3]=u*m,t[4]=(c*e-n*o)*m,t[5]=(n*r-a*e)*m,t[6]=d*m,t[7]=(i*o-l*e)*m,t[8]=(s*e-i*r)*m,this}transpose(){let t;const e=this.elements;return t=e[1],e[1]=e[3],e[3]=t,t=e[2],e[2]=e[6],e[6]=t,t=e[5],e[5]=e[7],e[7]=t,this}getNormalMatrix(t){return this.setFromMatrix4(t).invert().transpose()}transposeIntoArray(t){const e=this.elements;return t[0]=e[0],t[1]=e[3],t[2]=e[6],t[3]=e[1],t[4]=e[4],t[5]=e[7],t[6]=e[2],t[7]=e[5],t[8]=e[8],this}setUvTransform(t,e,i,n,r,s,a){const o=Math.cos(r),l=Math.sin(r);return this.set(i*o,i*l,-i*(o*s+l*a)+s+t,-n*l,n*o,-n*(-l*s+o*a)+a+e,0,0,1),this}scale(t,e){return this.premultiply(Pt.makeScale(t,e)),this}rotate(t){return this.premultiply(Pt.makeRotation(-t)),this}translate(t,e){return this.premultiply(Pt.makeTranslation(t,e)),this}makeTranslation(t,e){return this.set(1,0,t,0,1,e,0,0,1),this}makeRotation(t){const e=Math.cos(t),i=Math.sin(t);return this.set(e,-i,0,i,e,0,0,0,1),this}makeScale(t,e){return this.set(t,0,0,0,e,0,0,0,1),this}equals(t){const e=this.elements,i=t.elements;for(let t=0;t<9;t++)if(e[t]!==i[t])return!1;return!0}fromArray(t,e=0){for(let i=0;i<9;i++)this.elements[i]=t[i+e];return this}toArray(t=[],e=0){const i=this.elements;return t[e]=i[0],t[e+1]=i[1],t[e+2]=i[2],t[e+3]=i[3],t[e+4]=i[4],t[e+5]=i[5],t[e+6]=i[6],t[e+7]=i[7],t[e+8]=i[8],t}clone(){return(new this.constructor).fromArray(this.elements)}}const Pt=new Rt;function It(t){for(let e=t.length-1;e>=0;--e)if(t[e]>=65535)return!0;return!1}const Dt={Int8Array:Int8Array,Uint8Array:Uint8Array,Uint8ClampedArray:Uint8ClampedArray,Int16Array:Int16Array,Uint16Array:Uint16Array,Int32Array:Int32Array,Uint32Array:Uint32Array,Float32Array:Float32Array,Float64Array:Float64Array};function Nt(t,e){return new Dt[t](e)}function Ot(t){return document.createElementNS("http://www.w3.org/1999/xhtml",t)}function zt(t){return t<.04045?.0773993808*t:Math.pow(.9478672986*t+.0521327014,2.4)}function Ut(t){return t<.0031308?12.92*t:1.055*Math.pow(t,.41666)-.055}const Bt={[lt]:{[ct]:zt},[ct]:{[lt]:Ut}},Ft={legacyMode:!0,get workingColorSpace(){return ct},set workingColorSpace(t){console.warn("THREE.ColorManagement: .workingColorSpace is readonly.")},convert:function(t,e,i){if(this.legacyMode||e===i||!e||!i)return t;if(Bt[e]&&void 0!==Bt[e][i]){const n=Bt[e][i];return t.r=n(t.r),t.g=n(t.g),t.b=n(t.b),t}throw new Error("Unsupported color space conversion.")},fromWorkingColorSpace:function(t,e){return this.convert(t,this.workingColorSpace,e)},toWorkingColorSpace:function(t,e){return this.convert(t,e,this.workingColorSpace)}},kt={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074},Gt={r:0,g:0,b:0},Vt={h:0,s:0,l:0},Ht={h:0,s:0,l:0};function Wt(t,e,i){return i<0&&(i+=1),i>1&&(i-=1),i<1/6?t+6*(e-t)*i:i<.5?e:i<2/3?t+6*(e-t)*(2/3-i):t}function jt(t,e){return e.r=t.r,e.g=t.g,e.b=t.b,e}class qt{constructor(t,e,i){return this.isColor=!0,this.r=1,this.g=1,this.b=1,void 0===e&&void 0===i?this.set(t):this.setRGB(t,e,i)}set(t){return t&&t.isColor?this.copy(t):"number"==typeof t?this.setHex(t):"string"==typeof t&&this.setStyle(t),this}setScalar(t){return this.r=t,this.g=t,this.b=t,this}setHex(t,e="srgb"){return t=Math.floor(t),this.r=(t>>16&255)/255,this.g=(t>>8&255)/255,this.b=(255&t)/255,Ft.toWorkingColorSpace(this,e),this}setRGB(t,e,i,n=Ft.workingColorSpace){return this.r=t,this.g=e,this.b=i,Ft.toWorkingColorSpace(this,n),this}setHSL(t,e,i,n=Ft.workingColorSpace){if(t=Mt(t,1),e=yt(e,0,1),i=yt(i,0,1),0===e)this.r=this.g=this.b=i;else{const n=i<=.5?i*(1+e):i+e-i*e,r=2*i-n;this.r=Wt(r,n,t+1/3),this.g=Wt(r,n,t),this.b=Wt(r,n,t-1/3)}return Ft.toWorkingColorSpace(this,n),this}setStyle(t,e="srgb"){function i(e){void 0!==e&&parseFloat(e)<1&&console.warn("THREE.Color: Alpha component of "+t+" will be ignored.")}let n;if(n=/^((?:rgb|hsl)a?)\(([^\)]*)\)/.exec(t)){let t;const r=n[1],s=n[2];switch(r){case"rgb":case"rgba":if(t=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(s))return this.r=Math.min(255,parseInt(t[1],10))/255,this.g=Math.min(255,parseInt(t[2],10))/255,this.b=Math.min(255,parseInt(t[3],10))/255,Ft.toWorkingColorSpace(this,e),i(t[4]),this;if(t=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(s))return this.r=Math.min(100,parseInt(t[1],10))/100,this.g=Math.min(100,parseInt(t[2],10))/100,this.b=Math.min(100,parseInt(t[3],10))/100,Ft.toWorkingColorSpace(this,e),i(t[4]),this;break;case"hsl":case"hsla":if(t=/^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(s)){const n=parseFloat(t[1])/360,r=parseFloat(t[2])/100,s=parseFloat(t[3])/100;return i(t[4]),this.setHSL(n,r,s,e)}}}else if(n=/^\#([A-Fa-f\d]+)$/.exec(t)){const t=n[1],i=t.length;if(3===i)return this.r=parseInt(t.charAt(0)+t.charAt(0),16)/255,this.g=parseInt(t.charAt(1)+t.charAt(1),16)/255,this.b=parseInt(t.charAt(2)+t.charAt(2),16)/255,Ft.toWorkingColorSpace(this,e),this;if(6===i)return this.r=parseInt(t.charAt(0)+t.charAt(1),16)/255,this.g=parseInt(t.charAt(2)+t.charAt(3),16)/255,this.b=parseInt(t.charAt(4)+t.charAt(5),16)/255,Ft.toWorkingColorSpace(this,e),this}return t&&t.length>0?this.setColorName(t,e):this}setColorName(t,e="srgb"){const i=kt[t.toLowerCase()];return void 0!==i?this.setHex(i,e):console.warn("THREE.Color: Unknown color "+t),this}clone(){return new this.constructor(this.r,this.g,this.b)}copy(t){return this.r=t.r,this.g=t.g,this.b=t.b,this}copySRGBToLinear(t){return this.r=zt(t.r),this.g=zt(t.g),this.b=zt(t.b),this}copyLinearToSRGB(t){return this.r=Ut(t.r),this.g=Ut(t.g),this.b=Ut(t.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(t="srgb"){return Ft.fromWorkingColorSpace(jt(this,Gt),t),yt(255*Gt.r,0,255)<<16^yt(255*Gt.g,0,255)<<8^yt(255*Gt.b,0,255)<<0}getHexString(t="srgb"){return("000000"+this.getHex(t).toString(16)).slice(-6)}getHSL(t,e=Ft.workingColorSpace){Ft.fromWorkingColorSpace(jt(this,Gt),e);const i=Gt.r,n=Gt.g,r=Gt.b,s=Math.max(i,n,r),a=Math.min(i,n,r);let o,l;const c=(a+s)/2;if(a===s)o=0,l=0;else{const t=s-a;switch(l=c<=.5?t/(s+a):t/(2-s-a),s){case i:o=(n-r)/t+(n2048||e.height>2048?(console.warn("THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons",t),e.toDataURL("image/jpeg",.6)):e.toDataURL("image/png")}static sRGBToLinear(t){if("undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap){const e=Ot("canvas");e.width=t.width,e.height=t.height;const i=e.getContext("2d");i.drawImage(t,0,0,t.width,t.height);const n=i.getImageData(0,0,t.width,t.height),r=n.data;for(let t=0;t1)switch(this.wrapS){case c:t.x=t.x-Math.floor(t.x);break;case h:t.x=t.x<0?0:1;break;case u:1===Math.abs(Math.floor(t.x)%2)?t.x=Math.ceil(t.x)-t.x:t.x=t.x-Math.floor(t.x)}if(t.y<0||t.y>1)switch(this.wrapT){case c:t.y=t.y-Math.floor(t.y);break;case h:t.y=t.y<0?0:1;break;case u:1===Math.abs(Math.floor(t.y)%2)?t.y=Math.ceil(t.y)-t.y:t.y=t.y-Math.floor(t.y)}return this.flipY&&(t.y=1-t.y),t}set needsUpdate(t){!0===t&&(this.version++,this.source.needsUpdate=!0)}}$t.DEFAULT_IMAGE=null,$t.DEFAULT_MAPPING=n,$t.DEFAULT_ANISOTROPY=1;class Qt{constructor(t=0,e=0,i=0,n=1){Qt.prototype.isVector4=!0,this.x=t,this.y=e,this.z=i,this.w=n}get width(){return this.z}set width(t){this.z=t}get height(){return this.w}set height(t){this.w=t}set(t,e,i,n){return this.x=t,this.y=e,this.z=i,this.w=n,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this.w=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setW(t){return this.w=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;case 3:this.w=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;case 3:return this.w;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z,this.w)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this.w=void 0!==t.w?t.w:1,this}add(t){return this.x+=t.x,this.y+=t.y,this.z+=t.z,this.w+=t.w,this}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this.w+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this.w=t.w+e.w,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this.w+=t.w*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this.z-=t.z,this.w-=t.w,this}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this.w-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this.w=t.w-e.w,this}multiply(t){return this.x*=t.x,this.y*=t.y,this.z*=t.z,this.w*=t.w,this}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this.w*=t,this}applyMatrix4(t){const e=this.x,i=this.y,n=this.z,r=this.w,s=t.elements;return this.x=s[0]*e+s[4]*i+s[8]*n+s[12]*r,this.y=s[1]*e+s[5]*i+s[9]*n+s[13]*r,this.z=s[2]*e+s[6]*i+s[10]*n+s[14]*r,this.w=s[3]*e+s[7]*i+s[11]*n+s[15]*r,this}divideScalar(t){return this.multiplyScalar(1/t)}setAxisAngleFromQuaternion(t){this.w=2*Math.acos(t.w);const e=Math.sqrt(1-t.w*t.w);return e<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=t.x/e,this.y=t.y/e,this.z=t.z/e),this}setAxisAngleFromRotationMatrix(t){let e,i,n,r;const s=.01,a=.1,o=t.elements,l=o[0],c=o[4],h=o[8],u=o[1],d=o[5],p=o[9],m=o[2],f=o[6],g=o[10];if(Math.abs(c-u)o&&t>v?tv?o=0?1:-1,n=1-e*e;if(n>Number.EPSILON){const r=Math.sqrt(n),s=Math.atan2(r,e*i);t=Math.sin(t*s)/r,a=Math.sin(a*s)/r}const r=a*i;if(o=o*t+u*r,l=l*t+d*r,c=c*t+p*r,h=h*t+m*r,t===1-a){const t=1/Math.sqrt(o*o+l*l+c*c+h*h);o*=t,l*=t,c*=t,h*=t}}t[e]=o,t[e+1]=l,t[e+2]=c,t[e+3]=h}static multiplyQuaternionsFlat(t,e,i,n,r,s){const a=i[n],o=i[n+1],l=i[n+2],c=i[n+3],h=r[s],u=r[s+1],d=r[s+2],p=r[s+3];return t[e]=a*p+c*h+o*d-l*u,t[e+1]=o*p+c*u+l*h-a*d,t[e+2]=l*p+c*d+a*u-o*h,t[e+3]=c*p-a*h-o*u-l*d,t}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get w(){return this._w}set w(t){this._w=t,this._onChangeCallback()}set(t,e,i,n){return this._x=t,this._y=e,this._z=i,this._w=n,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._w)}copy(t){return this._x=t.x,this._y=t.y,this._z=t.z,this._w=t.w,this._onChangeCallback(),this}setFromEuler(t,e){const i=t._x,n=t._y,r=t._z,s=t._order,a=Math.cos,o=Math.sin,l=a(i/2),c=a(n/2),h=a(r/2),u=o(i/2),d=o(n/2),p=o(r/2);switch(s){case"XYZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"YXZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"ZXY":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"ZYX":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"YZX":this._x=u*c*h+l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h-u*d*p;break;case"XZY":this._x=u*c*h-l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h+u*d*p;break;default:console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: "+s)}return!1!==e&&this._onChangeCallback(),this}setFromAxisAngle(t,e){const i=e/2,n=Math.sin(i);return this._x=t.x*n,this._y=t.y*n,this._z=t.z*n,this._w=Math.cos(i),this._onChangeCallback(),this}setFromRotationMatrix(t){const e=t.elements,i=e[0],n=e[4],r=e[8],s=e[1],a=e[5],o=e[9],l=e[2],c=e[6],h=e[10],u=i+a+h;if(u>0){const t=.5/Math.sqrt(u+1);this._w=.25/t,this._x=(c-o)*t,this._y=(r-l)*t,this._z=(s-n)*t}else if(i>a&&i>h){const t=2*Math.sqrt(1+i-a-h);this._w=(c-o)/t,this._x=.25*t,this._y=(n+s)/t,this._z=(r+l)/t}else if(a>h){const t=2*Math.sqrt(1+a-i-h);this._w=(r-l)/t,this._x=(n+s)/t,this._y=.25*t,this._z=(o+c)/t}else{const t=2*Math.sqrt(1+h-i-a);this._w=(s-n)/t,this._x=(r+l)/t,this._y=(o+c)/t,this._z=.25*t}return this._onChangeCallback(),this}setFromUnitVectors(t,e){let i=t.dot(e)+1;return iMath.abs(t.z)?(this._x=-t.y,this._y=t.x,this._z=0,this._w=i):(this._x=0,this._y=-t.z,this._z=t.y,this._w=i)):(this._x=t.y*e.z-t.z*e.y,this._y=t.z*e.x-t.x*e.z,this._z=t.x*e.y-t.y*e.x,this._w=i),this.normalize()}angleTo(t){return 2*Math.acos(Math.abs(yt(this.dot(t),-1,1)))}rotateTowards(t,e){const i=this.angleTo(t);if(0===i)return this;const n=Math.min(1,e/i);return this.slerp(t,n),this}identity(){return this.set(0,0,0,1)}invert(){return this.conjugate()}conjugate(){return this._x*=-1,this._y*=-1,this._z*=-1,this._onChangeCallback(),this}dot(t){return this._x*t._x+this._y*t._y+this._z*t._z+this._w*t._w}lengthSq(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w}length(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)}normalize(){let t=this.length();return 0===t?(this._x=0,this._y=0,this._z=0,this._w=1):(t=1/t,this._x=this._x*t,this._y=this._y*t,this._z=this._z*t,this._w=this._w*t),this._onChangeCallback(),this}multiply(t){return this.multiplyQuaternions(this,t)}premultiply(t){return this.multiplyQuaternions(t,this)}multiplyQuaternions(t,e){const i=t._x,n=t._y,r=t._z,s=t._w,a=e._x,o=e._y,l=e._z,c=e._w;return this._x=i*c+s*a+n*l-r*o,this._y=n*c+s*o+r*a-i*l,this._z=r*c+s*l+i*o-n*a,this._w=s*c-i*a-n*o-r*l,this._onChangeCallback(),this}slerp(t,e){if(0===e)return this;if(1===e)return this.copy(t);const i=this._x,n=this._y,r=this._z,s=this._w;let a=s*t._w+i*t._x+n*t._y+r*t._z;if(a<0?(this._w=-t._w,this._x=-t._x,this._y=-t._y,this._z=-t._z,a=-a):this.copy(t),a>=1)return this._w=s,this._x=i,this._y=n,this._z=r,this;const o=1-a*a;if(o<=Number.EPSILON){const t=1-e;return this._w=t*s+e*this._w,this._x=t*i+e*this._x,this._y=t*n+e*this._y,this._z=t*r+e*this._z,this.normalize(),this._onChangeCallback(),this}const l=Math.sqrt(o),c=Math.atan2(l,a),h=Math.sin((1-e)*c)/l,u=Math.sin(e*c)/l;return this._w=s*h+this._w*u,this._x=i*h+this._x*u,this._y=n*h+this._y*u,this._z=r*h+this._z*u,this._onChangeCallback(),this}slerpQuaternions(t,e,i){return this.copy(t).slerp(e,i)}random(){const t=Math.random(),e=Math.sqrt(1-t),i=Math.sqrt(t),n=2*Math.PI*Math.random(),r=2*Math.PI*Math.random();return this.set(e*Math.cos(n),i*Math.sin(r),i*Math.cos(r),e*Math.sin(n))}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._w===this._w}fromArray(t,e=0){return this._x=t[e],this._y=t[e+1],this._z=t[e+2],this._w=t[e+3],this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._w,t}fromBufferAttribute(t,e){return this._x=t.getX(e),this._y=t.getY(e),this._z=t.getZ(e),this._w=t.getW(e),this}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._w}}class re{constructor(t=0,e=0,i=0){re.prototype.isVector3=!0,this.x=t,this.y=e,this.z=i}set(t,e,i){return void 0===i&&(i=this.z),this.x=t,this.y=e,this.z=i,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this}add(t){return this.x+=t.x,this.y+=t.y,this.z+=t.z,this}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this.z-=t.z,this}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this}multiply(t){return this.x*=t.x,this.y*=t.y,this.z*=t.z,this}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this}multiplyVectors(t,e){return this.x=t.x*e.x,this.y=t.y*e.y,this.z=t.z*e.z,this}applyEuler(t){return this.applyQuaternion(ae.setFromEuler(t))}applyAxisAngle(t,e){return this.applyQuaternion(ae.setFromAxisAngle(t,e))}applyMatrix3(t){const e=this.x,i=this.y,n=this.z,r=t.elements;return this.x=r[0]*e+r[3]*i+r[6]*n,this.y=r[1]*e+r[4]*i+r[7]*n,this.z=r[2]*e+r[5]*i+r[8]*n,this}applyNormalMatrix(t){return this.applyMatrix3(t).normalize()}applyMatrix4(t){const e=this.x,i=this.y,n=this.z,r=t.elements,s=1/(r[3]*e+r[7]*i+r[11]*n+r[15]);return this.x=(r[0]*e+r[4]*i+r[8]*n+r[12])*s,this.y=(r[1]*e+r[5]*i+r[9]*n+r[13])*s,this.z=(r[2]*e+r[6]*i+r[10]*n+r[14])*s,this}applyQuaternion(t){const e=this.x,i=this.y,n=this.z,r=t.x,s=t.y,a=t.z,o=t.w,l=o*e+s*n-a*i,c=o*i+a*e-r*n,h=o*n+r*i-s*e,u=-r*e-s*i-a*n;return this.x=l*o+u*-r+c*-a-h*-s,this.y=c*o+u*-s+h*-r-l*-a,this.z=h*o+u*-a+l*-s-c*-r,this}project(t){return this.applyMatrix4(t.matrixWorldInverse).applyMatrix4(t.projectionMatrix)}unproject(t){return this.applyMatrix4(t.projectionMatrixInverse).applyMatrix4(t.matrixWorld)}transformDirection(t){const e=this.x,i=this.y,n=this.z,r=t.elements;return this.x=r[0]*e+r[4]*i+r[8]*n,this.y=r[1]*e+r[5]*i+r[9]*n,this.z=r[2]*e+r[6]*i+r[10]*n,this.normalize()}divide(t){return this.x/=t.x,this.y/=t.y,this.z/=t.z,this}divideScalar(t){return this.multiplyScalar(1/t)}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this.z=Math.min(this.z,t.z),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this.z=Math.max(this.z,t.z),this}clamp(t,e){return this.x=Math.max(t.x,Math.min(e.x,this.x)),this.y=Math.max(t.y,Math.min(e.y,this.y)),this.z=Math.max(t.z,Math.min(e.z,this.z)),this}clampScalar(t,e){return this.x=Math.max(t,Math.min(e,this.x)),this.y=Math.max(t,Math.min(e,this.y)),this.z=Math.max(t,Math.min(e,this.z)),this}clampLength(t,e){const i=this.length();return this.divideScalar(i||1).multiplyScalar(Math.max(t,Math.min(e,i)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this}roundToZero(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this.z=this.z<0?Math.ceil(this.z):Math.floor(this.z),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this}dot(t){return this.x*t.x+this.y*t.y+this.z*t.z}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)}normalize(){return this.divideScalar(this.length()||1)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this.z+=(t.z-this.z)*e,this}lerpVectors(t,e,i){return this.x=t.x+(e.x-t.x)*i,this.y=t.y+(e.y-t.y)*i,this.z=t.z+(e.z-t.z)*i,this}cross(t){return this.crossVectors(this,t)}crossVectors(t,e){const i=t.x,n=t.y,r=t.z,s=e.x,a=e.y,o=e.z;return this.x=n*o-r*a,this.y=r*s-i*o,this.z=i*a-n*s,this}projectOnVector(t){const e=t.lengthSq();if(0===e)return this.set(0,0,0);const i=t.dot(this)/e;return this.copy(t).multiplyScalar(i)}projectOnPlane(t){return se.copy(this).projectOnVector(t),this.sub(se)}reflect(t){return this.sub(se.copy(t).multiplyScalar(2*this.dot(t)))}angleTo(t){const e=Math.sqrt(this.lengthSq()*t.lengthSq());if(0===e)return Math.PI/2;const i=this.dot(t)/e;return Math.acos(yt(i,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,i=this.y-t.y,n=this.z-t.z;return e*e+i*i+n*n}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)+Math.abs(this.z-t.z)}setFromSpherical(t){return this.setFromSphericalCoords(t.radius,t.phi,t.theta)}setFromSphericalCoords(t,e,i){const n=Math.sin(e)*t;return this.x=n*Math.sin(i),this.y=Math.cos(e)*t,this.z=n*Math.cos(i),this}setFromCylindrical(t){return this.setFromCylindricalCoords(t.radius,t.theta,t.y)}setFromCylindricalCoords(t,e,i){return this.x=t*Math.sin(e),this.y=i,this.z=t*Math.cos(e),this}setFromMatrixPosition(t){const e=t.elements;return this.x=e[12],this.y=e[13],this.z=e[14],this}setFromMatrixScale(t){const e=this.setFromMatrixColumn(t,0).length(),i=this.setFromMatrixColumn(t,1).length(),n=this.setFromMatrixColumn(t,2).length();return this.x=e,this.y=i,this.z=n,this}setFromMatrixColumn(t,e){return this.fromArray(t.elements,4*e)}setFromMatrix3Column(t,e){return this.fromArray(t.elements,3*e)}setFromEuler(t){return this.x=t._x,this.y=t._y,this.z=t._z,this}equals(t){return t.x===this.x&&t.y===this.y&&t.z===this.z}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this.z=t[e+2],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t[e+2]=this.z,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this.z=t.getZ(e),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}randomDirection(){const t=2*(Math.random()-.5),e=Math.random()*Math.PI*2,i=Math.sqrt(1-t**2);return this.x=i*Math.cos(e),this.y=i*Math.sin(e),this.z=t,this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}}const se=new re,ae=new ne;class oe{constructor(t=new re(1/0,1/0,1/0),e=new re(-1/0,-1/0,-1/0)){this.isBox3=!0,this.min=t,this.max=e}set(t,e){return this.min.copy(t),this.max.copy(e),this}setFromArray(t){let e=1/0,i=1/0,n=1/0,r=-1/0,s=-1/0,a=-1/0;for(let o=0,l=t.length;or&&(r=l),c>s&&(s=c),h>a&&(a=h)}return this.min.set(e,i,n),this.max.set(r,s,a),this}setFromBufferAttribute(t){let e=1/0,i=1/0,n=1/0,r=-1/0,s=-1/0,a=-1/0;for(let o=0,l=t.count;or&&(r=l),c>s&&(s=c),h>a&&(a=h)}return this.min.set(e,i,n),this.max.set(r,s,a),this}setFromPoints(t){this.makeEmpty();for(let e=0,i=t.length;ethis.max.x||t.ythis.max.y||t.zthis.max.z)}containsBox(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y&&this.min.z<=t.min.z&&t.max.z<=this.max.z}getParameter(t,e){return e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y),(t.z-this.min.z)/(this.max.z-this.min.z))}intersectsBox(t){return!(t.max.xthis.max.x||t.max.ythis.max.y||t.max.zthis.max.z)}intersectsSphere(t){return this.clampPoint(t.center,ce),ce.distanceToSquared(t.center)<=t.radius*t.radius}intersectsPlane(t){let e,i;return t.normal.x>0?(e=t.normal.x*this.min.x,i=t.normal.x*this.max.x):(e=t.normal.x*this.max.x,i=t.normal.x*this.min.x),t.normal.y>0?(e+=t.normal.y*this.min.y,i+=t.normal.y*this.max.y):(e+=t.normal.y*this.max.y,i+=t.normal.y*this.min.y),t.normal.z>0?(e+=t.normal.z*this.min.z,i+=t.normal.z*this.max.z):(e+=t.normal.z*this.max.z,i+=t.normal.z*this.min.z),e<=-t.constant&&i>=-t.constant}intersectsTriangle(t){if(this.isEmpty())return!1;this.getCenter(ve),xe.subVectors(this.max,ve),ue.subVectors(t.a,ve),de.subVectors(t.b,ve),pe.subVectors(t.c,ve),me.subVectors(de,ue),fe.subVectors(pe,de),ge.subVectors(ue,pe);let e=[0,-me.z,me.y,0,-fe.z,fe.y,0,-ge.z,ge.y,me.z,0,-me.x,fe.z,0,-fe.x,ge.z,0,-ge.x,-me.y,me.x,0,-fe.y,fe.x,0,-ge.y,ge.x,0];return!!Me(e,ue,de,pe,xe)&&(e=[1,0,0,0,1,0,0,0,1],!!Me(e,ue,de,pe,xe)&&(_e.crossVectors(me,fe),e=[_e.x,_e.y,_e.z],Me(e,ue,de,pe,xe)))}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return ce.copy(t).clamp(this.min,this.max).sub(t).length()}getBoundingSphere(t){return this.getCenter(t.center),t.radius=.5*this.getSize(ce).length(),t}intersect(t){return this.min.max(t.min),this.max.min(t.max),this.isEmpty()&&this.makeEmpty(),this}union(t){return this.min.min(t.min),this.max.max(t.max),this}applyMatrix4(t){return this.isEmpty()||(le[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(t),le[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(t),le[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(t),le[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(t),le[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(t),le[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(t),le[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(t),le[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(t),this.setFromPoints(le)),this}translate(t){return this.min.add(t),this.max.add(t),this}equals(t){return t.min.equals(this.min)&&t.max.equals(this.max)}}const le=[new re,new re,new re,new re,new re,new re,new re,new re],ce=new re,he=new oe,ue=new re,de=new re,pe=new re,me=new re,fe=new re,ge=new re,ve=new re,xe=new re,_e=new re,ye=new re;function Me(t,e,i,n,r){for(let s=0,a=t.length-3;s<=a;s+=3){ye.fromArray(t,s);const a=r.x*Math.abs(ye.x)+r.y*Math.abs(ye.y)+r.z*Math.abs(ye.z),o=e.dot(ye),l=i.dot(ye),c=n.dot(ye);if(Math.max(-Math.max(o,l,c),Math.min(o,l,c))>a)return!1}return!0}const be=new oe,we=new re,Se=new re;class Te{constructor(t=new re,e=-1){this.center=t,this.radius=e}set(t,e){return this.center.copy(t),this.radius=e,this}setFromPoints(t,e){const i=this.center;void 0!==e?i.copy(e):be.setFromPoints(t).getCenter(i);let n=0;for(let e=0,r=t.length;ethis.radius*this.radius&&(e.sub(this.center).normalize(),e.multiplyScalar(this.radius).add(this.center)),e}getBoundingBox(t){return this.isEmpty()?(t.makeEmpty(),t):(t.set(this.center,this.center),t.expandByScalar(this.radius),t)}applyMatrix4(t){return this.center.applyMatrix4(t),this.radius=this.radius*t.getMaxScaleOnAxis(),this}translate(t){return this.center.add(t),this}expandByPoint(t){if(this.isEmpty())return this.center.copy(t),this.radius=0,this;we.subVectors(t,this.center);const e=we.lengthSq();if(e>this.radius*this.radius){const t=Math.sqrt(e),i=.5*(t-this.radius);this.center.addScaledVector(we,i/t),this.radius+=i}return this}union(t){return t.isEmpty()?this:this.isEmpty()?(this.copy(t),this):(!0===this.center.equals(t.center)?this.radius=Math.max(this.radius,t.radius):(Se.subVectors(t.center,this.center).setLength(t.radius),this.expandByPoint(we.copy(t.center).add(Se)),this.expandByPoint(we.copy(t.center).sub(Se))),this)}equals(t){return t.center.equals(this.center)&&t.radius===this.radius}clone(){return(new this.constructor).copy(this)}}const Ae=new re,Ee=new re,Ce=new re,Le=new re,Re=new re,Pe=new re,Ie=new re;class De{constructor(t=new re,e=new re(0,0,-1)){this.origin=t,this.direction=e}set(t,e){return this.origin.copy(t),this.direction.copy(e),this}copy(t){return this.origin.copy(t.origin),this.direction.copy(t.direction),this}at(t,e){return e.copy(this.direction).multiplyScalar(t).add(this.origin)}lookAt(t){return this.direction.copy(t).sub(this.origin).normalize(),this}recast(t){return this.origin.copy(this.at(t,Ae)),this}closestPointToPoint(t,e){e.subVectors(t,this.origin);const i=e.dot(this.direction);return i<0?e.copy(this.origin):e.copy(this.direction).multiplyScalar(i).add(this.origin)}distanceToPoint(t){return Math.sqrt(this.distanceSqToPoint(t))}distanceSqToPoint(t){const e=Ae.subVectors(t,this.origin).dot(this.direction);return e<0?this.origin.distanceToSquared(t):(Ae.copy(this.direction).multiplyScalar(e).add(this.origin),Ae.distanceToSquared(t))}distanceSqToSegment(t,e,i,n){Ee.copy(t).add(e).multiplyScalar(.5),Ce.copy(e).sub(t).normalize(),Le.copy(this.origin).sub(Ee);const r=.5*t.distanceTo(e),s=-this.direction.dot(Ce),a=Le.dot(this.direction),o=-Le.dot(Ce),l=Le.lengthSq(),c=Math.abs(1-s*s);let h,u,d,p;if(c>0)if(h=s*o-a,u=s*a-o,p=r*c,h>=0)if(u>=-p)if(u<=p){const t=1/c;h*=t,u*=t,d=h*(h+s*u+2*a)+u*(s*h+u+2*o)+l}else u=r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;else u=-r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;else u<=-p?(h=Math.max(0,-(-s*r+a)),u=h>0?-r:Math.min(Math.max(-r,-o),r),d=-h*h+u*(u+2*o)+l):u<=p?(h=0,u=Math.min(Math.max(-r,-o),r),d=u*(u+2*o)+l):(h=Math.max(0,-(s*r+a)),u=h>0?r:Math.min(Math.max(-r,-o),r),d=-h*h+u*(u+2*o)+l);else u=s>0?-r:r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;return i&&i.copy(this.direction).multiplyScalar(h).add(this.origin),n&&n.copy(Ce).multiplyScalar(u).add(Ee),d}intersectSphere(t,e){Ae.subVectors(t.center,this.origin);const i=Ae.dot(this.direction),n=Ae.dot(Ae)-i*i,r=t.radius*t.radius;if(n>r)return null;const s=Math.sqrt(r-n),a=i-s,o=i+s;return a<0&&o<0?null:a<0?this.at(o,e):this.at(a,e)}intersectsSphere(t){return this.distanceSqToPoint(t.center)<=t.radius*t.radius}distanceToPlane(t){const e=t.normal.dot(this.direction);if(0===e)return 0===t.distanceToPoint(this.origin)?0:null;const i=-(this.origin.dot(t.normal)+t.constant)/e;return i>=0?i:null}intersectPlane(t,e){const i=this.distanceToPlane(t);return null===i?null:this.at(i,e)}intersectsPlane(t){const e=t.distanceToPoint(this.origin);if(0===e)return!0;return t.normal.dot(this.direction)*e<0}intersectBox(t,e){let i,n,r,s,a,o;const l=1/this.direction.x,c=1/this.direction.y,h=1/this.direction.z,u=this.origin;return l>=0?(i=(t.min.x-u.x)*l,n=(t.max.x-u.x)*l):(i=(t.max.x-u.x)*l,n=(t.min.x-u.x)*l),c>=0?(r=(t.min.y-u.y)*c,s=(t.max.y-u.y)*c):(r=(t.max.y-u.y)*c,s=(t.min.y-u.y)*c),i>s||r>n?null:((r>i||isNaN(i))&&(i=r),(s=0?(a=(t.min.z-u.z)*h,o=(t.max.z-u.z)*h):(a=(t.max.z-u.z)*h,o=(t.min.z-u.z)*h),i>o||a>n?null:((a>i||i!=i)&&(i=a),(o=0?i:n,e)))}intersectsBox(t){return null!==this.intersectBox(t,Ae)}intersectTriangle(t,e,i,n,r){Re.subVectors(e,t),Pe.subVectors(i,t),Ie.crossVectors(Re,Pe);let s,a=this.direction.dot(Ie);if(a>0){if(n)return null;s=1}else{if(!(a<0))return null;s=-1,a=-a}Le.subVectors(this.origin,t);const o=s*this.direction.dot(Pe.crossVectors(Le,Pe));if(o<0)return null;const l=s*this.direction.dot(Re.cross(Le));if(l<0)return null;if(o+l>a)return null;const c=-s*Le.dot(Ie);return c<0?null:this.at(c/a,r)}applyMatrix4(t){return this.origin.applyMatrix4(t),this.direction.transformDirection(t),this}equals(t){return t.origin.equals(this.origin)&&t.direction.equals(this.direction)}clone(){return(new this.constructor).copy(this)}}class Ne{constructor(){Ne.prototype.isMatrix4=!0,this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}set(t,e,i,n,r,s,a,o,l,c,h,u,d,p,m,f){const g=this.elements;return g[0]=t,g[4]=e,g[8]=i,g[12]=n,g[1]=r,g[5]=s,g[9]=a,g[13]=o,g[2]=l,g[6]=c,g[10]=h,g[14]=u,g[3]=d,g[7]=p,g[11]=m,g[15]=f,this}identity(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this}clone(){return(new Ne).fromArray(this.elements)}copy(t){const e=this.elements,i=t.elements;return e[0]=i[0],e[1]=i[1],e[2]=i[2],e[3]=i[3],e[4]=i[4],e[5]=i[5],e[6]=i[6],e[7]=i[7],e[8]=i[8],e[9]=i[9],e[10]=i[10],e[11]=i[11],e[12]=i[12],e[13]=i[13],e[14]=i[14],e[15]=i[15],this}copyPosition(t){const e=this.elements,i=t.elements;return e[12]=i[12],e[13]=i[13],e[14]=i[14],this}setFromMatrix3(t){const e=t.elements;return this.set(e[0],e[3],e[6],0,e[1],e[4],e[7],0,e[2],e[5],e[8],0,0,0,0,1),this}extractBasis(t,e,i){return t.setFromMatrixColumn(this,0),e.setFromMatrixColumn(this,1),i.setFromMatrixColumn(this,2),this}makeBasis(t,e,i){return this.set(t.x,e.x,i.x,0,t.y,e.y,i.y,0,t.z,e.z,i.z,0,0,0,0,1),this}extractRotation(t){const e=this.elements,i=t.elements,n=1/Oe.setFromMatrixColumn(t,0).length(),r=1/Oe.setFromMatrixColumn(t,1).length(),s=1/Oe.setFromMatrixColumn(t,2).length();return e[0]=i[0]*n,e[1]=i[1]*n,e[2]=i[2]*n,e[3]=0,e[4]=i[4]*r,e[5]=i[5]*r,e[6]=i[6]*r,e[7]=0,e[8]=i[8]*s,e[9]=i[9]*s,e[10]=i[10]*s,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromEuler(t){const e=this.elements,i=t.x,n=t.y,r=t.z,s=Math.cos(i),a=Math.sin(i),o=Math.cos(n),l=Math.sin(n),c=Math.cos(r),h=Math.sin(r);if("XYZ"===t.order){const t=s*c,i=s*h,n=a*c,r=a*h;e[0]=o*c,e[4]=-o*h,e[8]=l,e[1]=i+n*l,e[5]=t-r*l,e[9]=-a*o,e[2]=r-t*l,e[6]=n+i*l,e[10]=s*o}else if("YXZ"===t.order){const t=o*c,i=o*h,n=l*c,r=l*h;e[0]=t+r*a,e[4]=n*a-i,e[8]=s*l,e[1]=s*h,e[5]=s*c,e[9]=-a,e[2]=i*a-n,e[6]=r+t*a,e[10]=s*o}else if("ZXY"===t.order){const t=o*c,i=o*h,n=l*c,r=l*h;e[0]=t-r*a,e[4]=-s*h,e[8]=n+i*a,e[1]=i+n*a,e[5]=s*c,e[9]=r-t*a,e[2]=-s*l,e[6]=a,e[10]=s*o}else if("ZYX"===t.order){const t=s*c,i=s*h,n=a*c,r=a*h;e[0]=o*c,e[4]=n*l-i,e[8]=t*l+r,e[1]=o*h,e[5]=r*l+t,e[9]=i*l-n,e[2]=-l,e[6]=a*o,e[10]=s*o}else if("YZX"===t.order){const t=s*o,i=s*l,n=a*o,r=a*l;e[0]=o*c,e[4]=r-t*h,e[8]=n*h+i,e[1]=h,e[5]=s*c,e[9]=-a*c,e[2]=-l*c,e[6]=i*h+n,e[10]=t-r*h}else if("XZY"===t.order){const t=s*o,i=s*l,n=a*o,r=a*l;e[0]=o*c,e[4]=-h,e[8]=l*c,e[1]=t*h+r,e[5]=s*c,e[9]=i*h-n,e[2]=n*h-i,e[6]=a*c,e[10]=r*h+t}return e[3]=0,e[7]=0,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromQuaternion(t){return this.compose(Ue,t,Be)}lookAt(t,e,i){const n=this.elements;return Ge.subVectors(t,e),0===Ge.lengthSq()&&(Ge.z=1),Ge.normalize(),Fe.crossVectors(i,Ge),0===Fe.lengthSq()&&(1===Math.abs(i.z)?Ge.x+=1e-4:Ge.z+=1e-4,Ge.normalize(),Fe.crossVectors(i,Ge)),Fe.normalize(),ke.crossVectors(Ge,Fe),n[0]=Fe.x,n[4]=ke.x,n[8]=Ge.x,n[1]=Fe.y,n[5]=ke.y,n[9]=Ge.y,n[2]=Fe.z,n[6]=ke.z,n[10]=Ge.z,this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const i=t.elements,n=e.elements,r=this.elements,s=i[0],a=i[4],o=i[8],l=i[12],c=i[1],h=i[5],u=i[9],d=i[13],p=i[2],m=i[6],f=i[10],g=i[14],v=i[3],x=i[7],_=i[11],y=i[15],M=n[0],b=n[4],w=n[8],S=n[12],T=n[1],A=n[5],E=n[9],C=n[13],L=n[2],R=n[6],P=n[10],I=n[14],D=n[3],N=n[7],O=n[11],z=n[15];return r[0]=s*M+a*T+o*L+l*D,r[4]=s*b+a*A+o*R+l*N,r[8]=s*w+a*E+o*P+l*O,r[12]=s*S+a*C+o*I+l*z,r[1]=c*M+h*T+u*L+d*D,r[5]=c*b+h*A+u*R+d*N,r[9]=c*w+h*E+u*P+d*O,r[13]=c*S+h*C+u*I+d*z,r[2]=p*M+m*T+f*L+g*D,r[6]=p*b+m*A+f*R+g*N,r[10]=p*w+m*E+f*P+g*O,r[14]=p*S+m*C+f*I+g*z,r[3]=v*M+x*T+_*L+y*D,r[7]=v*b+x*A+_*R+y*N,r[11]=v*w+x*E+_*P+y*O,r[15]=v*S+x*C+_*I+y*z,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[4]*=t,e[8]*=t,e[12]*=t,e[1]*=t,e[5]*=t,e[9]*=t,e[13]*=t,e[2]*=t,e[6]*=t,e[10]*=t,e[14]*=t,e[3]*=t,e[7]*=t,e[11]*=t,e[15]*=t,this}determinant(){const t=this.elements,e=t[0],i=t[4],n=t[8],r=t[12],s=t[1],a=t[5],o=t[9],l=t[13],c=t[2],h=t[6],u=t[10],d=t[14];return t[3]*(+r*o*h-n*l*h-r*a*u+i*l*u+n*a*d-i*o*d)+t[7]*(+e*o*d-e*l*u+r*s*u-n*s*d+n*l*c-r*o*c)+t[11]*(+e*l*h-e*a*d-r*s*h+i*s*d+r*a*c-i*l*c)+t[15]*(-n*a*c-e*o*h+e*a*u+n*s*h-i*s*u+i*o*c)}transpose(){const t=this.elements;let e;return e=t[1],t[1]=t[4],t[4]=e,e=t[2],t[2]=t[8],t[8]=e,e=t[6],t[6]=t[9],t[9]=e,e=t[3],t[3]=t[12],t[12]=e,e=t[7],t[7]=t[13],t[13]=e,e=t[11],t[11]=t[14],t[14]=e,this}setPosition(t,e,i){const n=this.elements;return t.isVector3?(n[12]=t.x,n[13]=t.y,n[14]=t.z):(n[12]=t,n[13]=e,n[14]=i),this}invert(){const t=this.elements,e=t[0],i=t[1],n=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8],h=t[9],u=t[10],d=t[11],p=t[12],m=t[13],f=t[14],g=t[15],v=h*f*l-m*u*l+m*o*d-a*f*d-h*o*g+a*u*g,x=p*u*l-c*f*l-p*o*d+s*f*d+c*o*g-s*u*g,_=c*m*l-p*h*l+p*a*d-s*m*d-c*a*g+s*h*g,y=p*h*o-c*m*o-p*a*u+s*m*u+c*a*f-s*h*f,M=e*v+i*x+n*_+r*y;if(0===M)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);const b=1/M;return t[0]=v*b,t[1]=(m*u*r-h*f*r-m*n*d+i*f*d+h*n*g-i*u*g)*b,t[2]=(a*f*r-m*o*r+m*n*l-i*f*l-a*n*g+i*o*g)*b,t[3]=(h*o*r-a*u*r-h*n*l+i*u*l+a*n*d-i*o*d)*b,t[4]=x*b,t[5]=(c*f*r-p*u*r+p*n*d-e*f*d-c*n*g+e*u*g)*b,t[6]=(p*o*r-s*f*r-p*n*l+e*f*l+s*n*g-e*o*g)*b,t[7]=(s*u*r-c*o*r+c*n*l-e*u*l-s*n*d+e*o*d)*b,t[8]=_*b,t[9]=(p*h*r-c*m*r-p*i*d+e*m*d+c*i*g-e*h*g)*b,t[10]=(s*m*r-p*a*r+p*i*l-e*m*l-s*i*g+e*a*g)*b,t[11]=(c*a*r-s*h*r-c*i*l+e*h*l+s*i*d-e*a*d)*b,t[12]=y*b,t[13]=(c*m*n-p*h*n+p*i*u-e*m*u-c*i*f+e*h*f)*b,t[14]=(p*a*n-s*m*n-p*i*o+e*m*o+s*i*f-e*a*f)*b,t[15]=(s*h*n-c*a*n+c*i*o-e*h*o-s*i*u+e*a*u)*b,this}scale(t){const e=this.elements,i=t.x,n=t.y,r=t.z;return e[0]*=i,e[4]*=n,e[8]*=r,e[1]*=i,e[5]*=n,e[9]*=r,e[2]*=i,e[6]*=n,e[10]*=r,e[3]*=i,e[7]*=n,e[11]*=r,this}getMaxScaleOnAxis(){const t=this.elements,e=t[0]*t[0]+t[1]*t[1]+t[2]*t[2],i=t[4]*t[4]+t[5]*t[5]+t[6]*t[6],n=t[8]*t[8]+t[9]*t[9]+t[10]*t[10];return Math.sqrt(Math.max(e,i,n))}makeTranslation(t,e,i){return this.set(1,0,0,t,0,1,0,e,0,0,1,i,0,0,0,1),this}makeRotationX(t){const e=Math.cos(t),i=Math.sin(t);return this.set(1,0,0,0,0,e,-i,0,0,i,e,0,0,0,0,1),this}makeRotationY(t){const e=Math.cos(t),i=Math.sin(t);return this.set(e,0,i,0,0,1,0,0,-i,0,e,0,0,0,0,1),this}makeRotationZ(t){const e=Math.cos(t),i=Math.sin(t);return this.set(e,-i,0,0,i,e,0,0,0,0,1,0,0,0,0,1),this}makeRotationAxis(t,e){const i=Math.cos(e),n=Math.sin(e),r=1-i,s=t.x,a=t.y,o=t.z,l=r*s,c=r*a;return this.set(l*s+i,l*a-n*o,l*o+n*a,0,l*a+n*o,c*a+i,c*o-n*s,0,l*o-n*a,c*o+n*s,r*o*o+i,0,0,0,0,1),this}makeScale(t,e,i){return this.set(t,0,0,0,0,e,0,0,0,0,i,0,0,0,0,1),this}makeShear(t,e,i,n,r,s){return this.set(1,i,r,0,t,1,s,0,e,n,1,0,0,0,0,1),this}compose(t,e,i){const n=this.elements,r=e._x,s=e._y,a=e._z,o=e._w,l=r+r,c=s+s,h=a+a,u=r*l,d=r*c,p=r*h,m=s*c,f=s*h,g=a*h,v=o*l,x=o*c,_=o*h,y=i.x,M=i.y,b=i.z;return n[0]=(1-(m+g))*y,n[1]=(d+_)*y,n[2]=(p-x)*y,n[3]=0,n[4]=(d-_)*M,n[5]=(1-(u+g))*M,n[6]=(f+v)*M,n[7]=0,n[8]=(p+x)*b,n[9]=(f-v)*b,n[10]=(1-(u+m))*b,n[11]=0,n[12]=t.x,n[13]=t.y,n[14]=t.z,n[15]=1,this}decompose(t,e,i){const n=this.elements;let r=Oe.set(n[0],n[1],n[2]).length();const s=Oe.set(n[4],n[5],n[6]).length(),a=Oe.set(n[8],n[9],n[10]).length();this.determinant()<0&&(r=-r),t.x=n[12],t.y=n[13],t.z=n[14],ze.copy(this);const o=1/r,l=1/s,c=1/a;return ze.elements[0]*=o,ze.elements[1]*=o,ze.elements[2]*=o,ze.elements[4]*=l,ze.elements[5]*=l,ze.elements[6]*=l,ze.elements[8]*=c,ze.elements[9]*=c,ze.elements[10]*=c,e.setFromRotationMatrix(ze),i.x=r,i.y=s,i.z=a,this}makePerspective(t,e,i,n,r,s){const a=this.elements,o=2*r/(e-t),l=2*r/(i-n),c=(e+t)/(e-t),h=(i+n)/(i-n),u=-(s+r)/(s-r),d=-2*s*r/(s-r);return a[0]=o,a[4]=0,a[8]=c,a[12]=0,a[1]=0,a[5]=l,a[9]=h,a[13]=0,a[2]=0,a[6]=0,a[10]=u,a[14]=d,a[3]=0,a[7]=0,a[11]=-1,a[15]=0,this}makeOrthographic(t,e,i,n,r,s){const a=this.elements,o=1/(e-t),l=1/(i-n),c=1/(s-r),h=(e+t)*o,u=(i+n)*l,d=(s+r)*c;return a[0]=2*o,a[4]=0,a[8]=0,a[12]=-h,a[1]=0,a[5]=2*l,a[9]=0,a[13]=-u,a[2]=0,a[6]=0,a[10]=-2*c,a[14]=-d,a[3]=0,a[7]=0,a[11]=0,a[15]=1,this}equals(t){const e=this.elements,i=t.elements;for(let t=0;t<16;t++)if(e[t]!==i[t])return!1;return!0}fromArray(t,e=0){for(let i=0;i<16;i++)this.elements[i]=t[i+e];return this}toArray(t=[],e=0){const i=this.elements;return t[e]=i[0],t[e+1]=i[1],t[e+2]=i[2],t[e+3]=i[3],t[e+4]=i[4],t[e+5]=i[5],t[e+6]=i[6],t[e+7]=i[7],t[e+8]=i[8],t[e+9]=i[9],t[e+10]=i[10],t[e+11]=i[11],t[e+12]=i[12],t[e+13]=i[13],t[e+14]=i[14],t[e+15]=i[15],t}}const Oe=new re,ze=new Ne,Ue=new re(0,0,0),Be=new re(1,1,1),Fe=new re,ke=new re,Ge=new re,Ve=new Ne,He=new ne;class We{constructor(t=0,e=0,i=0,n=We.DefaultOrder){this.isEuler=!0,this._x=t,this._y=e,this._z=i,this._order=n}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get order(){return this._order}set order(t){this._order=t,this._onChangeCallback()}set(t,e,i,n=this._order){return this._x=t,this._y=e,this._z=i,this._order=n,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._order)}copy(t){return this._x=t._x,this._y=t._y,this._z=t._z,this._order=t._order,this._onChangeCallback(),this}setFromRotationMatrix(t,e=this._order,i=!0){const n=t.elements,r=n[0],s=n[4],a=n[8],o=n[1],l=n[5],c=n[9],h=n[2],u=n[6],d=n[10];switch(e){case"XYZ":this._y=Math.asin(yt(a,-1,1)),Math.abs(a)<.9999999?(this._x=Math.atan2(-c,d),this._z=Math.atan2(-s,r)):(this._x=Math.atan2(u,l),this._z=0);break;case"YXZ":this._x=Math.asin(-yt(c,-1,1)),Math.abs(c)<.9999999?(this._y=Math.atan2(a,d),this._z=Math.atan2(o,l)):(this._y=Math.atan2(-h,r),this._z=0);break;case"ZXY":this._x=Math.asin(yt(u,-1,1)),Math.abs(u)<.9999999?(this._y=Math.atan2(-h,d),this._z=Math.atan2(-s,l)):(this._y=0,this._z=Math.atan2(o,r));break;case"ZYX":this._y=Math.asin(-yt(h,-1,1)),Math.abs(h)<.9999999?(this._x=Math.atan2(u,d),this._z=Math.atan2(o,r)):(this._x=0,this._z=Math.atan2(-s,l));break;case"YZX":this._z=Math.asin(yt(o,-1,1)),Math.abs(o)<.9999999?(this._x=Math.atan2(-c,l),this._y=Math.atan2(-h,r)):(this._x=0,this._y=Math.atan2(a,d));break;case"XZY":this._z=Math.asin(-yt(s,-1,1)),Math.abs(s)<.9999999?(this._x=Math.atan2(u,l),this._y=Math.atan2(a,r)):(this._x=Math.atan2(-c,d),this._y=0);break;default:console.warn("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: "+e)}return this._order=e,!0===i&&this._onChangeCallback(),this}setFromQuaternion(t,e,i){return Ve.makeRotationFromQuaternion(t),this.setFromRotationMatrix(Ve,e,i)}setFromVector3(t,e=this._order){return this.set(t.x,t.y,t.z,e)}reorder(t){return He.setFromEuler(this),this.setFromQuaternion(He,t)}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._order===this._order}fromArray(t){return this._x=t[0],this._y=t[1],this._z=t[2],void 0!==t[3]&&(this._order=t[3]),this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._order,t}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._order}toVector3(){console.error("THREE.Euler: .toVector3() has been removed. Use Vector3.setFromEuler() instead")}}We.DefaultOrder="XYZ",We.RotationOrders=["XYZ","YZX","ZXY","XZY","YXZ","ZYX"];class je{constructor(){this.mask=1}set(t){this.mask=(1<>>0}enable(t){this.mask|=1<1){for(let t=0;t1){for(let t=0;t0){n.children=[];for(let e=0;e0){n.animations=[];for(let e=0;e0&&(i.geometries=e),n.length>0&&(i.materials=n),r.length>0&&(i.textures=r),a.length>0&&(i.images=a),o.length>0&&(i.shapes=o),l.length>0&&(i.skeletons=l),c.length>0&&(i.animations=c),h.length>0&&(i.nodes=h)}return i.object=n,i;function s(t){const e=[];for(const i in t){const n=t[i];delete n.metadata,e.push(n)}return e}}clone(t){return(new this.constructor).copy(this,t)}copy(t,e=!0){if(this.name=t.name,this.up.copy(t.up),this.position.copy(t.position),this.rotation.order=t.rotation.order,this.quaternion.copy(t.quaternion),this.scale.copy(t.scale),this.matrix.copy(t.matrix),this.matrixWorld.copy(t.matrixWorld),this.matrixAutoUpdate=t.matrixAutoUpdate,this.matrixWorldNeedsUpdate=t.matrixWorldNeedsUpdate,this.matrixWorldAutoUpdate=t.matrixWorldAutoUpdate,this.layers.mask=t.layers.mask,this.visible=t.visible,this.castShadow=t.castShadow,this.receiveShadow=t.receiveShadow,this.frustumCulled=t.frustumCulled,this.renderOrder=t.renderOrder,this.userData=JSON.parse(JSON.stringify(t.userData)),!0===e)for(let e=0;e0?n.multiplyScalar(1/Math.sqrt(r)):n.set(0,0,0)}static getBarycoord(t,e,i,n,r){ai.subVectors(n,e),oi.subVectors(i,e),li.subVectors(t,e);const s=ai.dot(ai),a=ai.dot(oi),o=ai.dot(li),l=oi.dot(oi),c=oi.dot(li),h=s*l-a*a;if(0===h)return r.set(-2,-1,-1);const u=1/h,d=(l*o-a*c)*u,p=(s*c-a*o)*u;return r.set(1-d-p,p,d)}static containsPoint(t,e,i,n){return this.getBarycoord(t,e,i,n,ci),ci.x>=0&&ci.y>=0&&ci.x+ci.y<=1}static getUV(t,e,i,n,r,s,a,o){return this.getBarycoord(t,e,i,n,ci),o.set(0,0),o.addScaledVector(r,ci.x),o.addScaledVector(s,ci.y),o.addScaledVector(a,ci.z),o}static isFrontFacing(t,e,i,n){return ai.subVectors(i,e),oi.subVectors(t,e),ai.cross(oi).dot(n)<0}set(t,e,i){return this.a.copy(t),this.b.copy(e),this.c.copy(i),this}setFromPointsAndIndices(t,e,i,n){return this.a.copy(t[e]),this.b.copy(t[i]),this.c.copy(t[n]),this}setFromAttributeAndIndices(t,e,i,n){return this.a.fromBufferAttribute(t,e),this.b.fromBufferAttribute(t,i),this.c.fromBufferAttribute(t,n),this}clone(){return(new this.constructor).copy(this)}copy(t){return this.a.copy(t.a),this.b.copy(t.b),this.c.copy(t.c),this}getArea(){return ai.subVectors(this.c,this.b),oi.subVectors(this.a,this.b),.5*ai.cross(oi).length()}getMidpoint(t){return t.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(t){return gi.getNormal(this.a,this.b,this.c,t)}getPlane(t){return t.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(t,e){return gi.getBarycoord(t,this.a,this.b,this.c,e)}getUV(t,e,i,n,r){return gi.getUV(t,this.a,this.b,this.c,e,i,n,r)}containsPoint(t){return gi.containsPoint(t,this.a,this.b,this.c)}isFrontFacing(t){return gi.isFrontFacing(this.a,this.b,this.c,t)}intersectsBox(t){return t.intersectsTriangle(this)}closestPointToPoint(t,e){const i=this.a,n=this.b,r=this.c;let s,a;hi.subVectors(n,i),ui.subVectors(r,i),pi.subVectors(t,i);const o=hi.dot(pi),l=ui.dot(pi);if(o<=0&&l<=0)return e.copy(i);mi.subVectors(t,n);const c=hi.dot(mi),h=ui.dot(mi);if(c>=0&&h<=c)return e.copy(n);const u=o*h-c*l;if(u<=0&&o>=0&&c<=0)return s=o/(o-c),e.copy(i).addScaledVector(hi,s);fi.subVectors(t,r);const d=hi.dot(fi),p=ui.dot(fi);if(p>=0&&d<=p)return e.copy(r);const m=d*l-o*p;if(m<=0&&l>=0&&p<=0)return a=l/(l-p),e.copy(i).addScaledVector(ui,a);const f=c*p-d*h;if(f<=0&&h-c>=0&&d-p>=0)return di.subVectors(r,n),a=(h-c)/(h-c+(d-p)),e.copy(n).addScaledVector(di,a);const g=1/(f+m+u);return s=m*g,a=u*g,e.copy(i).addScaledVector(hi,s).addScaledVector(ui,a)}equals(t){return t.a.equals(this.a)&&t.b.equals(this.b)&&t.c.equals(this.c)}}let vi=0;class xi extends mt{constructor(){super(),this.isMaterial=!0,Object.defineProperty(this,"id",{value:vi++}),this.uuid=_t(),this.name="",this.type="Material",this.blending=1,this.side=0,this.vertexColors=!1,this.opacity=1,this.transparent=!1,this.blendSrc=204,this.blendDst=205,this.blendEquation=i,this.blendSrcAlpha=null,this.blendDstAlpha=null,this.blendEquationAlpha=null,this.depthFunc=3,this.depthTest=!0,this.depthWrite=!0,this.stencilWriteMask=255,this.stencilFunc=519,this.stencilRef=0,this.stencilFuncMask=255,this.stencilFail=ht,this.stencilZFail=ht,this.stencilZPass=ht,this.stencilWrite=!1,this.clippingPlanes=null,this.clipIntersection=!1,this.clipShadows=!1,this.shadowSide=null,this.colorWrite=!0,this.precision=null,this.polygonOffset=!1,this.polygonOffsetFactor=0,this.polygonOffsetUnits=0,this.dithering=!1,this.alphaToCoverage=!1,this.premultipliedAlpha=!1,this.visible=!0,this.toneMapped=!0,this.userData={},this.version=0,this._alphaTest=0}get alphaTest(){return this._alphaTest}set alphaTest(t){this._alphaTest>0!=t>0&&this.version++,this._alphaTest=t}onBuild(){}onBeforeRender(){}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(t){if(void 0!==t)for(const e in t){const i=t[e];if(void 0===i){console.warn("THREE.Material: '"+e+"' parameter is undefined.");continue}const n=this[e];void 0!==n?n&&n.isColor?n.set(i):n&&n.isVector3&&i&&i.isVector3?n.copy(i):this[e]=i:console.warn("THREE."+this.type+": '"+e+"' is not a property of this material.")}}toJSON(t){const e=void 0===t||"string"==typeof t;e&&(t={textures:{},images:{}});const i={metadata:{version:4.5,type:"Material",generator:"Material.toJSON"}};function n(t){const e=[];for(const i in t){const n=t[i];delete n.metadata,e.push(n)}return e}if(i.uuid=this.uuid,i.type=this.type,""!==this.name&&(i.name=this.name),this.color&&this.color.isColor&&(i.color=this.color.getHex()),void 0!==this.roughness&&(i.roughness=this.roughness),void 0!==this.metalness&&(i.metalness=this.metalness),void 0!==this.sheen&&(i.sheen=this.sheen),this.sheenColor&&this.sheenColor.isColor&&(i.sheenColor=this.sheenColor.getHex()),void 0!==this.sheenRoughness&&(i.sheenRoughness=this.sheenRoughness),this.emissive&&this.emissive.isColor&&(i.emissive=this.emissive.getHex()),this.emissiveIntensity&&1!==this.emissiveIntensity&&(i.emissiveIntensity=this.emissiveIntensity),this.specular&&this.specular.isColor&&(i.specular=this.specular.getHex()),void 0!==this.specularIntensity&&(i.specularIntensity=this.specularIntensity),this.specularColor&&this.specularColor.isColor&&(i.specularColor=this.specularColor.getHex()),void 0!==this.shininess&&(i.shininess=this.shininess),void 0!==this.clearcoat&&(i.clearcoat=this.clearcoat),void 0!==this.clearcoatRoughness&&(i.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&&this.clearcoatMap.isTexture&&(i.clearcoatMap=this.clearcoatMap.toJSON(t).uuid),this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture&&(i.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(t).uuid),this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture&&(i.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(t).uuid,i.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),void 0!==this.iridescence&&(i.iridescence=this.iridescence),void 0!==this.iridescenceIOR&&(i.iridescenceIOR=this.iridescenceIOR),void 0!==this.iridescenceThicknessRange&&(i.iridescenceThicknessRange=this.iridescenceThicknessRange),this.iridescenceMap&&this.iridescenceMap.isTexture&&(i.iridescenceMap=this.iridescenceMap.toJSON(t).uuid),this.iridescenceThicknessMap&&this.iridescenceThicknessMap.isTexture&&(i.iridescenceThicknessMap=this.iridescenceThicknessMap.toJSON(t).uuid),this.map&&this.map.isTexture&&(i.map=this.map.toJSON(t).uuid),this.matcap&&this.matcap.isTexture&&(i.matcap=this.matcap.toJSON(t).uuid),this.alphaMap&&this.alphaMap.isTexture&&(i.alphaMap=this.alphaMap.toJSON(t).uuid),this.lightMap&&this.lightMap.isTexture&&(i.lightMap=this.lightMap.toJSON(t).uuid,i.lightMapIntensity=this.lightMapIntensity),this.aoMap&&this.aoMap.isTexture&&(i.aoMap=this.aoMap.toJSON(t).uuid,i.aoMapIntensity=this.aoMapIntensity),this.bumpMap&&this.bumpMap.isTexture&&(i.bumpMap=this.bumpMap.toJSON(t).uuid,i.bumpScale=this.bumpScale),this.normalMap&&this.normalMap.isTexture&&(i.normalMap=this.normalMap.toJSON(t).uuid,i.normalMapType=this.normalMapType,i.normalScale=this.normalScale.toArray()),this.displacementMap&&this.displacementMap.isTexture&&(i.displacementMap=this.displacementMap.toJSON(t).uuid,i.displacementScale=this.displacementScale,i.displacementBias=this.displacementBias),this.roughnessMap&&this.roughnessMap.isTexture&&(i.roughnessMap=this.roughnessMap.toJSON(t).uuid),this.metalnessMap&&this.metalnessMap.isTexture&&(i.metalnessMap=this.metalnessMap.toJSON(t).uuid),this.emissiveMap&&this.emissiveMap.isTexture&&(i.emissiveMap=this.emissiveMap.toJSON(t).uuid),this.specularMap&&this.specularMap.isTexture&&(i.specularMap=this.specularMap.toJSON(t).uuid),this.specularIntensityMap&&this.specularIntensityMap.isTexture&&(i.specularIntensityMap=this.specularIntensityMap.toJSON(t).uuid),this.specularColorMap&&this.specularColorMap.isTexture&&(i.specularColorMap=this.specularColorMap.toJSON(t).uuid),this.envMap&&this.envMap.isTexture&&(i.envMap=this.envMap.toJSON(t).uuid,void 0!==this.combine&&(i.combine=this.combine)),void 0!==this.envMapIntensity&&(i.envMapIntensity=this.envMapIntensity),void 0!==this.reflectivity&&(i.reflectivity=this.reflectivity),void 0!==this.refractionRatio&&(i.refractionRatio=this.refractionRatio),this.gradientMap&&this.gradientMap.isTexture&&(i.gradientMap=this.gradientMap.toJSON(t).uuid),void 0!==this.transmission&&(i.transmission=this.transmission),this.transmissionMap&&this.transmissionMap.isTexture&&(i.transmissionMap=this.transmissionMap.toJSON(t).uuid),void 0!==this.thickness&&(i.thickness=this.thickness),this.thicknessMap&&this.thicknessMap.isTexture&&(i.thicknessMap=this.thicknessMap.toJSON(t).uuid),void 0!==this.attenuationDistance&&this.attenuationDistance!==1/0&&(i.attenuationDistance=this.attenuationDistance),void 0!==this.attenuationColor&&(i.attenuationColor=this.attenuationColor.getHex()),void 0!==this.size&&(i.size=this.size),null!==this.shadowSide&&(i.shadowSide=this.shadowSide),void 0!==this.sizeAttenuation&&(i.sizeAttenuation=this.sizeAttenuation),1!==this.blending&&(i.blending=this.blending),0!==this.side&&(i.side=this.side),this.vertexColors&&(i.vertexColors=!0),this.opacity<1&&(i.opacity=this.opacity),!0===this.transparent&&(i.transparent=this.transparent),i.depthFunc=this.depthFunc,i.depthTest=this.depthTest,i.depthWrite=this.depthWrite,i.colorWrite=this.colorWrite,i.stencilWrite=this.stencilWrite,i.stencilWriteMask=this.stencilWriteMask,i.stencilFunc=this.stencilFunc,i.stencilRef=this.stencilRef,i.stencilFuncMask=this.stencilFuncMask,i.stencilFail=this.stencilFail,i.stencilZFail=this.stencilZFail,i.stencilZPass=this.stencilZPass,void 0!==this.rotation&&0!==this.rotation&&(i.rotation=this.rotation),!0===this.polygonOffset&&(i.polygonOffset=!0),0!==this.polygonOffsetFactor&&(i.polygonOffsetFactor=this.polygonOffsetFactor),0!==this.polygonOffsetUnits&&(i.polygonOffsetUnits=this.polygonOffsetUnits),void 0!==this.linewidth&&1!==this.linewidth&&(i.linewidth=this.linewidth),void 0!==this.dashSize&&(i.dashSize=this.dashSize),void 0!==this.gapSize&&(i.gapSize=this.gapSize),void 0!==this.scale&&(i.scale=this.scale),!0===this.dithering&&(i.dithering=!0),this.alphaTest>0&&(i.alphaTest=this.alphaTest),!0===this.alphaToCoverage&&(i.alphaToCoverage=this.alphaToCoverage),!0===this.premultipliedAlpha&&(i.premultipliedAlpha=this.premultipliedAlpha),!0===this.wireframe&&(i.wireframe=this.wireframe),this.wireframeLinewidth>1&&(i.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(i.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(i.wireframeLinejoin=this.wireframeLinejoin),!0===this.flatShading&&(i.flatShading=this.flatShading),!1===this.visible&&(i.visible=!1),!1===this.toneMapped&&(i.toneMapped=!1),!1===this.fog&&(i.fog=!1),"{}"!==JSON.stringify(this.userData)&&(i.userData=this.userData),e){const e=n(t.textures),r=n(t.images);e.length>0&&(i.textures=e),r.length>0&&(i.images=r)}return i}clone(){return(new this.constructor).copy(this)}copy(t){this.name=t.name,this.blending=t.blending,this.side=t.side,this.vertexColors=t.vertexColors,this.opacity=t.opacity,this.transparent=t.transparent,this.blendSrc=t.blendSrc,this.blendDst=t.blendDst,this.blendEquation=t.blendEquation,this.blendSrcAlpha=t.blendSrcAlpha,this.blendDstAlpha=t.blendDstAlpha,this.blendEquationAlpha=t.blendEquationAlpha,this.depthFunc=t.depthFunc,this.depthTest=t.depthTest,this.depthWrite=t.depthWrite,this.stencilWriteMask=t.stencilWriteMask,this.stencilFunc=t.stencilFunc,this.stencilRef=t.stencilRef,this.stencilFuncMask=t.stencilFuncMask,this.stencilFail=t.stencilFail,this.stencilZFail=t.stencilZFail,this.stencilZPass=t.stencilZPass,this.stencilWrite=t.stencilWrite;const e=t.clippingPlanes;let i=null;if(null!==e){const t=e.length;i=new Array(t);for(let n=0;n!==t;++n)i[n]=e[n].clone()}return this.clippingPlanes=i,this.clipIntersection=t.clipIntersection,this.clipShadows=t.clipShadows,this.shadowSide=t.shadowSide,this.colorWrite=t.colorWrite,this.precision=t.precision,this.polygonOffset=t.polygonOffset,this.polygonOffsetFactor=t.polygonOffsetFactor,this.polygonOffsetUnits=t.polygonOffsetUnits,this.dithering=t.dithering,this.alphaTest=t.alphaTest,this.alphaToCoverage=t.alphaToCoverage,this.premultipliedAlpha=t.premultipliedAlpha,this.visible=t.visible,this.toneMapped=t.toneMapped,this.userData=JSON.parse(JSON.stringify(t.userData)),this}dispose(){this.dispatchEvent({type:"dispose"})}set needsUpdate(t){!0===t&&this.version++}}class _i extends xi{constructor(t){super(),this.isMeshBasicMaterial=!0,this.type="MeshBasicMaterial",this.color=new qt(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.fog=t.fog,this}}const yi=new re,Mi=new Lt;class bi{constructor(t,e,i){if(Array.isArray(t))throw new TypeError("THREE.BufferAttribute: array should be a Typed Array.");this.isBufferAttribute=!0,this.name="",this.array=t,this.itemSize=e,this.count=void 0!==t?t.length/e:0,this.normalized=!0===i,this.usage=ut,this.updateRange={offset:0,count:-1},this.version=0}onUploadCallback(){}set needsUpdate(t){!0===t&&this.version++}setUsage(t){return this.usage=t,this}copy(t){return this.name=t.name,this.array=new t.array.constructor(t.array),this.itemSize=t.itemSize,this.count=t.count,this.normalized=t.normalized,this.usage=t.usage,this}copyAt(t,e,i){t*=this.itemSize,i*=e.itemSize;for(let n=0,r=this.itemSize;n0&&(t.userData=this.userData),void 0!==this.parameters){const e=this.parameters;for(const i in e)void 0!==e[i]&&(t[i]=e[i]);return t}t.data={attributes:{}};const e=this.index;null!==e&&(t.data.index={type:e.array.constructor.name,array:Array.prototype.slice.call(e.array)});const i=this.attributes;for(const e in i){const n=i[e];t.data.attributes[e]=n.toJSON(t.data)}const n={};let r=!1;for(const e in this.morphAttributes){const i=this.morphAttributes[e],s=[];for(let e=0,n=i.length;e0&&(n[e]=s,r=!0)}r&&(t.data.morphAttributes=n,t.data.morphTargetsRelative=this.morphTargetsRelative);const s=this.groups;s.length>0&&(t.data.groups=JSON.parse(JSON.stringify(s)));const a=this.boundingSphere;return null!==a&&(t.data.boundingSphere={center:a.center.toArray(),radius:a.radius}),t}clone(){return(new this.constructor).copy(this)}copy(t){this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null;const e={};this.name=t.name;const i=t.index;null!==i&&this.setIndex(i.clone(e));const n=t.attributes;for(const t in n){const i=n[t];this.setAttribute(t,i.clone(e))}const r=t.morphAttributes;for(const t in r){const i=[],n=r[t];for(let t=0,r=n.length;t0){const i=t[e[0]];if(void 0!==i){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=i.length;ti.far?null:{distance:c,point:Ji.clone(),object:t}}(t,e,i,n,Ui,Bi,Fi,Zi);if(p){o&&(qi.fromBufferAttribute(o,c),Xi.fromBufferAttribute(o,h),Yi.fromBufferAttribute(o,u),p.uv=gi.getUV(Zi,Ui,Bi,Fi,qi,Xi,Yi,new Lt)),l&&(qi.fromBufferAttribute(l,c),Xi.fromBufferAttribute(l,h),Yi.fromBufferAttribute(l,u),p.uv2=gi.getUV(Zi,Ui,Bi,Fi,qi,Xi,Yi,new Lt));const t={a:c,b:h,c:u,normal:new re,materialIndex:0};gi.getNormal(Ui,Bi,Fi,t.normal),p.face=t}return p}class Qi extends Di{constructor(t=1,e=1,i=1,n=1,r=1,s=1){super(),this.type="BoxGeometry",this.parameters={width:t,height:e,depth:i,widthSegments:n,heightSegments:r,depthSegments:s};const a=this;n=Math.floor(n),r=Math.floor(r),s=Math.floor(s);const o=[],l=[],c=[],h=[];let u=0,d=0;function p(t,e,i,n,r,s,p,m,f,g,v){const x=s/f,_=p/g,y=s/2,M=p/2,b=m/2,w=f+1,S=g+1;let T=0,A=0;const E=new re;for(let s=0;s0?1:-1,c.push(E.x,E.y,E.z),h.push(o/f),h.push(1-s/g),T+=1}}for(let t=0;t0&&(e.defines=this.defines),e.vertexShader=this.vertexShader,e.fragmentShader=this.fragmentShader;const i={};for(const t in this.extensions)!0===this.extensions[t]&&(i[t]=!0);return Object.keys(i).length>0&&(e.extensions=i),e}}class an extends si{constructor(){super(),this.isCamera=!0,this.type="Camera",this.matrixWorldInverse=new Ne,this.projectionMatrix=new Ne,this.projectionMatrixInverse=new Ne}copy(t,e){return super.copy(t,e),this.matrixWorldInverse.copy(t.matrixWorldInverse),this.projectionMatrix.copy(t.projectionMatrix),this.projectionMatrixInverse.copy(t.projectionMatrixInverse),this}getWorldDirection(t){this.updateWorldMatrix(!0,!1);const e=this.matrixWorld.elements;return t.set(-e[8],-e[9],-e[10]).normalize()}updateMatrixWorld(t){super.updateMatrixWorld(t),this.matrixWorldInverse.copy(this.matrixWorld).invert()}updateWorldMatrix(t,e){super.updateWorldMatrix(t,e),this.matrixWorldInverse.copy(this.matrixWorld).invert()}clone(){return(new this.constructor).copy(this)}}class on extends an{constructor(t=50,e=1,i=.1,n=2e3){super(),this.isPerspectiveCamera=!0,this.type="PerspectiveCamera",this.fov=t,this.zoom=1,this.near=i,this.far=n,this.focus=10,this.aspect=e,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}copy(t,e){return super.copy(t,e),this.fov=t.fov,this.zoom=t.zoom,this.near=t.near,this.far=t.far,this.focus=t.focus,this.aspect=t.aspect,this.view=null===t.view?null:Object.assign({},t.view),this.filmGauge=t.filmGauge,this.filmOffset=t.filmOffset,this}setFocalLength(t){const e=.5*this.getFilmHeight()/t;this.fov=2*xt*Math.atan(e),this.updateProjectionMatrix()}getFocalLength(){const t=Math.tan(.5*vt*this.fov);return.5*this.getFilmHeight()/t}getEffectiveFOV(){return 2*xt*Math.atan(Math.tan(.5*vt*this.fov)/this.zoom)}getFilmWidth(){return this.filmGauge*Math.min(this.aspect,1)}getFilmHeight(){return this.filmGauge/Math.max(this.aspect,1)}setViewOffset(t,e,i,n,r,s){this.aspect=t/e,null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=i,this.view.offsetY=n,this.view.width=r,this.view.height=s,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const t=this.near;let e=t*Math.tan(.5*vt*this.fov)/this.zoom,i=2*e,n=this.aspect*i,r=-.5*n;const s=this.view;if(null!==this.view&&this.view.enabled){const t=s.fullWidth,a=s.fullHeight;r+=s.offsetX*n/t,e-=s.offsetY*i/a,n*=s.width/t,i*=s.height/a}const a=this.filmOffset;0!==a&&(r+=t*a/this.getFilmWidth()),this.projectionMatrix.makePerspective(r,r+n,e,e-i,t,this.far),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(t){const e=super.toJSON(t);return e.object.fov=this.fov,e.object.zoom=this.zoom,e.object.near=this.near,e.object.far=this.far,e.object.focus=this.focus,e.object.aspect=this.aspect,null!==this.view&&(e.object.view=Object.assign({},this.view)),e.object.filmGauge=this.filmGauge,e.object.filmOffset=this.filmOffset,e}}const ln=-90;class cn extends si{constructor(t,e,i){super(),this.type="CubeCamera",this.renderTarget=i;const n=new on(ln,1,t,e);n.layers=this.layers,n.up.set(0,1,0),n.lookAt(1,0,0),this.add(n);const r=new on(ln,1,t,e);r.layers=this.layers,r.up.set(0,1,0),r.lookAt(-1,0,0),this.add(r);const s=new on(ln,1,t,e);s.layers=this.layers,s.up.set(0,0,-1),s.lookAt(0,1,0),this.add(s);const a=new on(ln,1,t,e);a.layers=this.layers,a.up.set(0,0,1),a.lookAt(0,-1,0),this.add(a);const o=new on(ln,1,t,e);o.layers=this.layers,o.up.set(0,1,0),o.lookAt(0,0,1),this.add(o);const l=new on(ln,1,t,e);l.layers=this.layers,l.up.set(0,1,0),l.lookAt(0,0,-1),this.add(l)}update(t,e){null===this.parent&&this.updateMatrixWorld();const i=this.renderTarget,[n,r,s,a,o,l]=this.children,c=t.getRenderTarget(),h=t.toneMapping,u=t.xr.enabled;t.toneMapping=0,t.xr.enabled=!1;const d=i.texture.generateMipmaps;i.texture.generateMipmaps=!1,t.setRenderTarget(i,0),t.render(e,n),t.setRenderTarget(i,1),t.render(e,r),t.setRenderTarget(i,2),t.render(e,s),t.setRenderTarget(i,3),t.render(e,a),t.setRenderTarget(i,4),t.render(e,o),i.texture.generateMipmaps=d,t.setRenderTarget(i,5),t.render(e,l),t.setRenderTarget(c),t.toneMapping=h,t.xr.enabled=u,i.texture.needsPMREMUpdate=!0}}class hn extends $t{constructor(t,e,i,n,s,a,o,l,c,h){super(t=void 0!==t?t:[],e=void 0!==e?e:r,i,n,s,a,o,l,c,h),this.isCubeTexture=!0,this.flipY=!1}get images(){return this.image}set images(t){this.image=t}}class un extends te{constructor(t=1,e={}){super(t,t,e),this.isWebGLCubeRenderTarget=!0;const i={width:t,height:t,depth:1},n=[i,i,i,i,i,i];this.texture=new hn(n,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.encoding),this.texture.isRenderTargetTexture=!0,this.texture.generateMipmaps=void 0!==e.generateMipmaps&&e.generateMipmaps,this.texture.minFilter=void 0!==e.minFilter?e.minFilter:f}fromEquirectangularTexture(t,e){this.texture.type=e.type,this.texture.encoding=e.encoding,this.texture.generateMipmaps=e.generateMipmaps,this.texture.minFilter=e.minFilter,this.texture.magFilter=e.magFilter;const i={uniforms:{tEquirect:{value:null}},vertexShader:"\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\tvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\n\t\t\t\t\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n\n\t\t\t\t}\n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvWorldDirection = transformDirection( position, modelMatrix );\n\n\t\t\t\t\t#include \n\t\t\t\t\t#include \n\n\t\t\t\t}\n\t\t\t",fragmentShader:"\n\n\t\t\t\tuniform sampler2D tEquirect;\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\t#include \n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvec3 direction = normalize( vWorldDirection );\n\n\t\t\t\t\tvec2 sampleUV = equirectUv( direction );\n\n\t\t\t\t\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\n\t\t\t\t}\n\t\t\t"},n=new Qi(5,5,5),r=new sn({name:"CubemapFromEquirect",uniforms:tn(i.uniforms),vertexShader:i.vertexShader,fragmentShader:i.fragmentShader,side:1,blending:0});r.uniforms.tEquirect.value=e;const s=new Ki(n,r),a=e.minFilter;e.minFilter===v&&(e.minFilter=f);return new cn(1,10,this).update(t,s),e.minFilter=a,s.geometry.dispose(),s.material.dispose(),this}clear(t,e,i,n){const r=t.getRenderTarget();for(let r=0;r<6;r++)t.setRenderTarget(this,r),t.clear(e,i,n);t.setRenderTarget(r)}}const dn=new re,pn=new re,mn=new Rt;class fn{constructor(t=new re(1,0,0),e=0){this.isPlane=!0,this.normal=t,this.constant=e}set(t,e){return this.normal.copy(t),this.constant=e,this}setComponents(t,e,i,n){return this.normal.set(t,e,i),this.constant=n,this}setFromNormalAndCoplanarPoint(t,e){return this.normal.copy(t),this.constant=-e.dot(this.normal),this}setFromCoplanarPoints(t,e,i){const n=dn.subVectors(i,e).cross(pn.subVectors(t,e)).normalize();return this.setFromNormalAndCoplanarPoint(n,t),this}copy(t){return this.normal.copy(t.normal),this.constant=t.constant,this}normalize(){const t=1/this.normal.length();return this.normal.multiplyScalar(t),this.constant*=t,this}negate(){return this.constant*=-1,this.normal.negate(),this}distanceToPoint(t){return this.normal.dot(t)+this.constant}distanceToSphere(t){return this.distanceToPoint(t.center)-t.radius}projectPoint(t,e){return e.copy(this.normal).multiplyScalar(-this.distanceToPoint(t)).add(t)}intersectLine(t,e){const i=t.delta(dn),n=this.normal.dot(i);if(0===n)return 0===this.distanceToPoint(t.start)?e.copy(t.start):null;const r=-(t.start.dot(this.normal)+this.constant)/n;return r<0||r>1?null:e.copy(i).multiplyScalar(r).add(t.start)}intersectsLine(t){const e=this.distanceToPoint(t.start),i=this.distanceToPoint(t.end);return e<0&&i>0||i<0&&e>0}intersectsBox(t){return t.intersectsPlane(this)}intersectsSphere(t){return t.intersectsPlane(this)}coplanarPoint(t){return t.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(t,e){const i=e||mn.getNormalMatrix(t),n=this.coplanarPoint(dn).applyMatrix4(t),r=this.normal.applyMatrix3(i).normalize();return this.constant=-n.dot(r),this}translate(t){return this.constant-=t.dot(this.normal),this}equals(t){return t.normal.equals(this.normal)&&t.constant===this.constant}clone(){return(new this.constructor).copy(this)}}const gn=new Te,vn=new re;class xn{constructor(t=new fn,e=new fn,i=new fn,n=new fn,r=new fn,s=new fn){this.planes=[t,e,i,n,r,s]}set(t,e,i,n,r,s){const a=this.planes;return a[0].copy(t),a[1].copy(e),a[2].copy(i),a[3].copy(n),a[4].copy(r),a[5].copy(s),this}copy(t){const e=this.planes;for(let i=0;i<6;i++)e[i].copy(t.planes[i]);return this}setFromProjectionMatrix(t){const e=this.planes,i=t.elements,n=i[0],r=i[1],s=i[2],a=i[3],o=i[4],l=i[5],c=i[6],h=i[7],u=i[8],d=i[9],p=i[10],m=i[11],f=i[12],g=i[13],v=i[14],x=i[15];return e[0].setComponents(a-n,h-o,m-u,x-f).normalize(),e[1].setComponents(a+n,h+o,m+u,x+f).normalize(),e[2].setComponents(a+r,h+l,m+d,x+g).normalize(),e[3].setComponents(a-r,h-l,m-d,x-g).normalize(),e[4].setComponents(a-s,h-c,m-p,x-v).normalize(),e[5].setComponents(a+s,h+c,m+p,x+v).normalize(),this}intersectsObject(t){const e=t.geometry;return null===e.boundingSphere&&e.computeBoundingSphere(),gn.copy(e.boundingSphere).applyMatrix4(t.matrixWorld),this.intersectsSphere(gn)}intersectsSprite(t){return gn.center.set(0,0,0),gn.radius=.7071067811865476,gn.applyMatrix4(t.matrixWorld),this.intersectsSphere(gn)}intersectsSphere(t){const e=this.planes,i=t.center,n=-t.radius;for(let t=0;t<6;t++){if(e[t].distanceToPoint(i)0?t.max.x:t.min.x,vn.y=n.normal.y>0?t.max.y:t.min.y,vn.z=n.normal.z>0?t.max.z:t.min.z,n.distanceToPoint(vn)<0)return!1}return!0}containsPoint(t){const e=this.planes;for(let i=0;i<6;i++)if(e[i].distanceToPoint(t)<0)return!1;return!0}clone(){return(new this.constructor).copy(this)}}function _n(){let t=null,e=!1,i=null,n=null;function r(e,s){i(e,s),n=t.requestAnimationFrame(r)}return{start:function(){!0!==e&&null!==i&&(n=t.requestAnimationFrame(r),e=!0)},stop:function(){t.cancelAnimationFrame(n),e=!1},setAnimationLoop:function(t){i=t},setContext:function(e){t=e}}}function yn(t,e){const i=e.isWebGL2,n=new WeakMap;return{get:function(t){return t.isInterleavedBufferAttribute&&(t=t.data),n.get(t)},remove:function(e){e.isInterleavedBufferAttribute&&(e=e.data);const i=n.get(e);i&&(t.deleteBuffer(i.buffer),n.delete(e))},update:function(e,r){if(e.isGLBufferAttribute){const t=n.get(e);return void((!t||t.version 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, 1.0, dotVH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif",iridescence_fragment:"#ifdef USE_IRIDESCENCE\n\tconst mat3 XYZ_TO_REC709 = mat3(\n\t\t 3.2404542, -0.9692660,\t0.0556434,\n\t\t-1.5371385,\t1.8760108, -0.2040259,\n\t\t-0.4985314,\t0.0415560,\t1.0572252\n\t);\n\tvec3 Fresnel0ToIor( vec3 fresnel0 ) {\n\t\tvec3 sqrtF0 = sqrt( fresnel0 );\n\t\treturn ( vec3( 1.0 ) + sqrtF0 ) / ( vec3( 1.0 ) - sqrtF0 );\n\t}\n\tvec3 IorToFresnel0( vec3 transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - vec3( incidentIor ) ) / ( transmittedIor + vec3( incidentIor ) ) );\n\t}\n\tfloat IorToFresnel0( float transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - incidentIor ) / ( transmittedIor + incidentIor ));\n\t}\n\tvec3 evalSensitivity( float OPD, vec3 shift ) {\n\t\tfloat phase = 2.0 * PI * OPD * 1.0e-9;\n\t\tvec3 val = vec3( 5.4856e-13, 4.4201e-13, 5.2481e-13 );\n\t\tvec3 pos = vec3( 1.6810e+06, 1.7953e+06, 2.2084e+06 );\n\t\tvec3 var = vec3( 4.3278e+09, 9.3046e+09, 6.6121e+09 );\n\t\tvec3 xyz = val * sqrt( 2.0 * PI * var ) * cos( pos * phase + shift ) * exp( - pow2( phase ) * var );\n\t\txyz.x += 9.7470e-14 * sqrt( 2.0 * PI * 4.5282e+09 ) * cos( 2.2399e+06 * phase + shift[ 0 ] ) * exp( - 4.5282e+09 * pow2( phase ) );\n\t\txyz /= 1.0685e-7;\n\t\tvec3 rgb = XYZ_TO_REC709 * xyz;\n\t\treturn rgb;\n\t}\n\tvec3 evalIridescence( float outsideIOR, float eta2, float cosTheta1, float thinFilmThickness, vec3 baseF0 ) {\n\t\tvec3 I;\n\t\tfloat iridescenceIOR = mix( outsideIOR, eta2, smoothstep( 0.0, 0.03, thinFilmThickness ) );\n\t\tfloat sinTheta2Sq = pow2( outsideIOR / iridescenceIOR ) * ( 1.0 - pow2( cosTheta1 ) );\n\t\tfloat cosTheta2Sq = 1.0 - sinTheta2Sq;\n\t\tif ( cosTheta2Sq < 0.0 ) {\n\t\t\t return vec3( 1.0 );\n\t\t}\n\t\tfloat cosTheta2 = sqrt( cosTheta2Sq );\n\t\tfloat R0 = IorToFresnel0( iridescenceIOR, outsideIOR );\n\t\tfloat R12 = F_Schlick( R0, 1.0, cosTheta1 );\n\t\tfloat R21 = R12;\n\t\tfloat T121 = 1.0 - R12;\n\t\tfloat phi12 = 0.0;\n\t\tif ( iridescenceIOR < outsideIOR ) phi12 = PI;\n\t\tfloat phi21 = PI - phi12;\n\t\tvec3 baseIOR = Fresnel0ToIor( clamp( baseF0, 0.0, 0.9999 ) );\t\tvec3 R1 = IorToFresnel0( baseIOR, iridescenceIOR );\n\t\tvec3 R23 = F_Schlick( R1, 1.0, cosTheta2 );\n\t\tvec3 phi23 = vec3( 0.0 );\n\t\tif ( baseIOR[ 0 ] < iridescenceIOR ) phi23[ 0 ] = PI;\n\t\tif ( baseIOR[ 1 ] < iridescenceIOR ) phi23[ 1 ] = PI;\n\t\tif ( baseIOR[ 2 ] < iridescenceIOR ) phi23[ 2 ] = PI;\n\t\tfloat OPD = 2.0 * iridescenceIOR * thinFilmThickness * cosTheta2;\n\t\tvec3 phi = vec3( phi21 ) + phi23;\n\t\tvec3 R123 = clamp( R12 * R23, 1e-5, 0.9999 );\n\t\tvec3 r123 = sqrt( R123 );\n\t\tvec3 Rs = pow2( T121 ) * R23 / ( vec3( 1.0 ) - R123 );\n\t\tvec3 C0 = R12 + Rs;\n\t\tI = C0;\n\t\tvec3 Cm = Rs - T121;\n\t\tfor ( int m = 1; m <= 2; ++ m ) {\n\t\t\tCm *= r123;\n\t\t\tvec3 Sm = 2.0 * evalSensitivity( float( m ) * OPD, float( m ) * phi );\n\t\t\tI += Cm * Sm;\n\t\t}\n\t\treturn max( I, vec3( 0.0 ) );\n\t}\n#endif",bumpmap_pars_fragment:"#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) {\n\t\tvec3 vSigmaX = dFdx( surf_pos.xyz );\n\t\tvec3 vSigmaY = dFdy( surf_pos.xyz );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 ) * faceDirection;\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif",clipping_planes_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#pragma unroll_loop_end\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\tif ( clipped ) discard;\n\t#endif\n#endif",clipping_planes_pars_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif",clipping_planes_pars_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif",clipping_planes_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif",color_fragment:"#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif",color_pars_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvarying vec3 vColor;\n#endif",color_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif",common:"#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nvec3 pow2( const in vec3 x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat luminance( const in vec3 rgb ) {\n\tconst vec3 weights = vec3( 0.2126729, 0.7151522, 0.0721750 );\n\treturn dot( weights, rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}",cube_uv_reflection_fragment:"#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\tvec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tuv.x += filterInt * 3.0 * cubeUV_minTileSize;\n\t\tuv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n\t\tuv.x *= CUBEUV_TEXEL_WIDTH;\n\t\tuv.y *= CUBEUV_TEXEL_HEIGHT;\n\t\t#ifdef texture2DGradEXT\n\t\t\treturn texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n\t\t#else\n\t\t\treturn texture2D( envMap, uv ).rgb;\n\t\t#endif\n\t}\n\t#define cubeUV_r0 1.0\n\t#define cubeUV_v0 0.339\n\t#define cubeUV_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_v1 0.276\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_v4 0.046\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_v5 0.016\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\n\t#define cubeUV_v6 0.0038\n\t#define cubeUV_m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= cubeUV_r1 ) {\n\t\t\tmip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0;\n\t\t} else if ( roughness >= cubeUV_r4 ) {\n\t\t\tmip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1;\n\t\t} else if ( roughness >= cubeUV_r5 ) {\n\t\t\tmip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4;\n\t\t} else if ( roughness >= cubeUV_r6 ) {\n\t\t\tmip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif",defaultnormal_vertex:"vec3 transformedNormal = objectNormal;\n#ifdef USE_INSTANCING\n\tmat3 m = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) );\n\ttransformedNormal = m * transformedNormal;\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\n#endif",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif",encodings_fragment:"gl_FragColor = linearToOutputTexel( gl_FragColor );",encodings_pars_fragment:"vec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}",envmap_fragment:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif",envmap_common_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif",envmap_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif",envmap_pars_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif",envmap_physical_pars_fragment:"#if defined( USE_ENVMAP )\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n#endif",envmap_vertex:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif",fog_vertex:"#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, vFogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif",fog_pars_fragment:"#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float vFogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif",gradientmap_pars_fragment:"#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\tvec2 fw = fwidth( coord ) * 0.5;\n\t\treturn mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) );\n\t#endif\n}",lightmap_fragment:"#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif",lightmap_pars_fragment:"#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif",lights_lambert_fragment:"LambertMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularStrength = specularStrength;",lights_lambert_pars_fragment:"varying vec3 vViewPosition;\nstruct LambertMaterial {\n\tvec3 diffuseColor;\n\tfloat specularStrength;\n};\nvoid RE_Direct_Lambert( const in IncidentLight directLight, const in GeometricContext geometry, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in GeometricContext geometry, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Lambert\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Lambert",lights_pars_begin:"uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\t#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tif ( cutoffDistance > 0.0 ) {\n\t\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\t}\n\t\treturn distanceFalloff;\n\t#else\n\t\tif ( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\t\treturn pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t\t}\n\t\treturn 1.0;\n\t#endif\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif",lights_toon_fragment:"ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;",lights_toon_pars_fragment:"varying vec3 vViewPosition;\nstruct ToonMaterial {\n\tvec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon",lights_phong_fragment:"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;",lights_phong_pars_fragment:"varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong",lights_physical_fragment:"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\tmaterial.ior = ior;\n\t#ifdef SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULARINTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vUv ).a;\n\t\t#endif\n\t\t#ifdef USE_SPECULARCOLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vUv ).rgb;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vUv ).a;\n\t#endif\n#endif",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n};\nvec3 clearcoatSpecular = vec3( 0.0 );\nvec3 sheenSpecular = vec3( 0.0 );\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3(\t\t0, 1,\t\t0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecular += ccIrradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.clearcoatNormal, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * BRDF_Sheen( directLight.direction, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\treflectedLight.directSpecular += irradiance * BRDF_GGX_Iridescence( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness );\n\t#else\n\t\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.roughness );\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecular += clearcoatRadiance * EnvironmentBRDF( geometry.clearcoatNormal, geometry.viewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * material.sheenColor * IBLSheenBRDF( geometry.normal, geometry.viewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}",lights_fragment_begin:"\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n#ifdef USE_CLEARCOAT\n\tgeometry.clearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometry.viewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence > 0.0 ) {\n\t\tmaterial.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n\t}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometry, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\tirradiance += getLightProbeIrradiance( lightProbe, geometry.normal );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry.normal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif",lights_fragment_maps:"#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometry.normal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness );\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif",lights_fragment_end:"#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );\n#endif",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t\tvarying float vIsPerspective;\n\t#else\n\t\tuniform float logDepthBufFC;\n\t#endif\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n\t#else\n\t\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\n\t\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\t\tgl_Position.z *= gl_Position.w;\n\t\t}\n\t#endif\n#endif",map_fragment:"#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\tsampledDiffuseColor = vec4( mix( pow( sampledDiffuseColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), sampledDiffuseColor.rgb * 0.0773993808, vec3( lessThanEqual( sampledDiffuseColor.rgb, vec3( 0.04045 ) ) ) ), sampledDiffuseColor.w );\n\t#endif\n\tdiffuseColor *= sampledDiffuseColor;\n#endif",map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif",map_particle_fragment:"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif",map_particle_pars_fragment:"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tuniform mat3 uvTransform;\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif",metalnessmap_fragment:"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphcolor_vertex:"#if defined( USE_MORPHCOLORS ) && defined( MORPHTARGETS_TEXTURE )\n\tvColor *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t#if defined( USE_COLOR_ALPHA )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];\n\t\t#elif defined( USE_COLOR )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];\n\t\t#endif\n\t}\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\t\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\t\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\t\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n\t#endif\n#endif",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t\tuniform sampler2DArray morphTargetsTexture;\n\t\tuniform ivec2 morphTargetsTextureSize;\n\t\tvec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n\t\t\tint texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n\t\t\tint y = texelIndex / morphTargetsTextureSize.x;\n\t\t\tint x = texelIndex - y * morphTargetsTextureSize.x;\n\t\t\tivec3 morphUV = ivec3( x, y, morphTargetIndex );\n\t\t\treturn texelFetch( morphTargetsTexture, morphUV, 0 );\n\t\t}\n\t#else\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\tuniform float morphTargetInfluences[ 8 ];\n\t\t#else\n\t\t\tuniform float morphTargetInfluences[ 4 ];\n\t\t#endif\n\t#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\t\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\t\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\t\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t\t#endif\n\t#endif\n#endif",normal_fragment_begin:"float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = dFdx( vViewPosition );\n\tvec3 fdy = dFdy( vViewPosition );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\t#ifdef USE_TANGENT\n\t\tvec3 tangent = normalize( vTangent );\n\t\tvec3 bitangent = normalize( vBitangent );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\ttangent = tangent * faceDirection;\n\t\t\tbitangent = bitangent * faceDirection;\n\t\t#endif\n\t\t#if defined( TANGENTSPACE_NORMALMAP ) || defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tmat3 vTBN = mat3( tangent, bitangent, normal );\n\t\t#endif\n\t#endif\n#endif\nvec3 geometryNormal = normal;",normal_fragment_maps:"#ifdef OBJECTSPACE_NORMALMAP\n\tnormal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( TANGENTSPACE_NORMALMAP )\n\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\t#ifdef USE_TANGENT\n\t\tnormal = normalize( vTBN * mapN );\n\t#else\n\t\tnormal = perturbNormal2Arb( - vViewPosition, normal, mapN, faceDirection );\n\t#endif\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif",normal_pars_fragment:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_pars_vertex:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_vertex:"#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif",normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef OBJECTSPACE_NORMALMAP\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( TANGENTSPACE_NORMALMAP ) || defined ( USE_CLEARCOAT_NORMALMAP ) )\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN, float faceDirection ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : faceDirection * inversesqrt( det );\n\t\treturn normalize( T * ( mapN.x * scale ) + B * ( mapN.y * scale ) + N * mapN.z );\n\t}\n#endif",clearcoat_normal_fragment_begin:"#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = geometryNormal;\n#endif",clearcoat_normal_fragment_maps:"#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\t#ifdef USE_TANGENT\n\t\tclearcoatNormal = normalize( vTBN * clearcoatMapN );\n\t#else\n\t\tclearcoatNormal = perturbNormal2Arb( - vViewPosition, clearcoatNormal, clearcoatMapN, faceDirection );\n\t#endif\n#endif",clearcoat_pars_fragment:"#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif",iridescence_pars_fragment:"#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif",output_fragment:"#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha + 0.1;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );",packing:"vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nvec2 packDepthToRG( in highp float v ) {\n\treturn packDepthToRGBA( v ).yx;\n}\nfloat unpackRGToDepth( const in highp vec2 v ) {\n\treturn unpackRGBAToDepth( vec4( v.xy, 0.0, 0.0 ) );\n}\nvec4 pack2HalfToRGBA( vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}",premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif",project_vertex:"vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;",dithering_fragment:"#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif",dithering_pars_fragment:"#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif",roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t\tf.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t\tf.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif",shadowmap_pars_vertex:"#if NUM_SPOT_LIGHT_COORDS > 0\n\tuniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif",shadowmap_vertex:"#if defined( USE_SHADOWMAP ) || ( NUM_SPOT_LIGHT_COORDS > 0 )\n\t#if NUM_DIR_LIGHT_SHADOWS > 0 || NUM_SPOT_LIGHT_COORDS > 0 || NUM_POINT_LIGHT_SHADOWS > 0\n\t\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\tvec4 shadowWorldPosition;\n\t#endif\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_COORDS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition;\n\t\t#if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t\tshadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias;\n\t\t#endif\n\t\tvSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n#endif",shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}",skinbase_vertex:"#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\tuniform highp sampler2D boneTexture;\n\tuniform int boneTextureSize;\n\tmat4 getBoneMatrix( const in float i ) {\n\t\tfloat j = i * 4.0;\n\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\ty = dy * ( y + 0.5 );\n\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\treturn bone;\n\t}\n#endif",skinning_vertex:"#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif",skinnormal_vertex:"#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif",specularmap_fragment:"float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif",specularmap_pars_fragment:"#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif",tonemapping_fragment:"#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif",tonemapping_pars_fragment:"#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3(\t1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108,\t1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605,\t1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }",transmission_fragment:"#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmission = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmission.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmission.rgb, material.transmission );\n#endif",transmission_pars_fragment:"#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat framebufferLod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\t#ifdef texture2DLodEXT\n\t\t\treturn texture2DLodEXT( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#else\n\t\t\treturn texture2D( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#endif\n\t}\n\tvec3 applyVolumeAttenuation( const in vec3 radiance, const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn radiance;\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance * radiance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 attenuatedColor = applyVolumeAttenuation( transmittedLight.rgb, length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor * diffuseColor, transmittedLight.a );\n\t}\n#endif",uv_pars_fragment:"#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n\tvarying vec2 vUv;\n#endif",uv_pars_vertex:"#ifdef USE_UV\n\t#ifdef UVS_VERTEX_ONLY\n\t\tvec2 vUv;\n\t#else\n\t\tvarying vec2 vUv;\n\t#endif\n\tuniform mat3 uvTransform;\n#endif",uv_vertex:"#ifdef USE_UV\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif",uv2_pars_fragment:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif",uv2_pars_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n\tuniform mat3 uv2Transform;\n#endif",uv2_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif",background_vert:"varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}",background_frag:"uniform sampler2D t2D;\nuniform float backgroundIntensity;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\ttexColor = vec4( mix( pow( texColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), texColor.rgb * 0.0773993808, vec3( lessThanEqual( texColor.rgb, vec3( 0.04045 ) ) ) ), texColor.w );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}",backgroundCube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",backgroundCube_frag:"#ifdef ENVMAP_TYPE_CUBE\n\tuniform samplerCube envMap;\n#elif defined( ENVMAP_TYPE_CUBE_UV )\n\tuniform sampler2D envMap;\n#endif\nuniform float flipEnvMap;\nuniform float backgroundBlurriness;\nuniform float backgroundIntensity;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, vWorldDirection, backgroundBlurriness );\n\t#else\n\t\tvec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}",cube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",cube_frag:"uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldDirection;\nvoid main() {\n\tvec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) );\n\tgl_FragColor = texColor;\n\tgl_FragColor.a *= opacity;\n\t#include \n\t#include \n}",depth_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvHighPrecisionZW = gl_Position.zw;\n}",depth_frag:"#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#endif\n}",distanceRGBA_vert:"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}",distanceRGBA_frag:"#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main () {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}",equirect_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}",equirect_frag:"uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\t#include \n\t#include \n}",linedashed_vert:"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",linedashed_frag:"uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_vert:"#define LAMBERT\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_frag:"#define LAMBERT\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshmatcap_vert:"#define MATCAP\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n}",meshmatcap_frag:"#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#else\n\t\tvec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshnormal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}",meshnormal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}",meshphong_vert:"#define PHONG\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphong_frag:"#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphysical_vert:"#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}",meshphysical_frag:"#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULARINTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n\t#ifdef USE_SPECULARCOLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshtoon_vert:"#define TOON\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}",meshtoon_frag:"#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",points_vert:"uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}",points_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_vert:"#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_frag:"uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n\t#include \n\t#include \n}",sprite_vert:"uniform float rotation;\nuniform vec2 center;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}",sprite_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n}"},wn={common:{diffuse:{value:new qt(16777215)},opacity:{value:1},map:{value:null},uvTransform:{value:new Rt},uv2Transform:{value:new Rt},alphaMap:{value:null},alphaTest:{value:0}},specularmap:{specularMap:{value:null}},envmap:{envMap:{value:null},flipEnvMap:{value:-1},reflectivity:{value:1},ior:{value:1.5},refractionRatio:{value:.98}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1}},emissivemap:{emissiveMap:{value:null}},bumpmap:{bumpMap:{value:null},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalScale:{value:new Lt(1,1)}},displacementmap:{displacementMap:{value:null},displacementScale:{value:1},displacementBias:{value:0}},roughnessmap:{roughnessMap:{value:null}},metalnessmap:{metalnessMap:{value:null}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:25e-5},fogNear:{value:1},fogFar:{value:2e3},fogColor:{value:new qt(16777215)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMap:{value:[]},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},spotLightMap:{value:[]},spotShadowMap:{value:[]},spotLightMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{},shadowCameraNear:{},shadowCameraFar:{}}},pointShadowMap:{value:[]},pointShadowMatrix:{value:[]},hemisphereLights:{value:[],properties:{direction:{},skyColor:{},groundColor:{}}},rectAreaLights:{value:[],properties:{color:{},position:{},width:{},height:{}}},ltc_1:{value:null},ltc_2:{value:null}},points:{diffuse:{value:new qt(16777215)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},alphaTest:{value:0},uvTransform:{value:new Rt}},sprite:{diffuse:{value:new qt(16777215)},opacity:{value:1},center:{value:new Lt(.5,.5)},rotation:{value:0},map:{value:null},alphaMap:{value:null},alphaTest:{value:0},uvTransform:{value:new Rt}}},Sn={basic:{uniforms:en([wn.common,wn.specularmap,wn.envmap,wn.aomap,wn.lightmap,wn.fog]),vertexShader:bn.meshbasic_vert,fragmentShader:bn.meshbasic_frag},lambert:{uniforms:en([wn.common,wn.specularmap,wn.envmap,wn.aomap,wn.lightmap,wn.emissivemap,wn.bumpmap,wn.normalmap,wn.displacementmap,wn.fog,wn.lights,{emissive:{value:new qt(0)}}]),vertexShader:bn.meshlambert_vert,fragmentShader:bn.meshlambert_frag},phong:{uniforms:en([wn.common,wn.specularmap,wn.envmap,wn.aomap,wn.lightmap,wn.emissivemap,wn.bumpmap,wn.normalmap,wn.displacementmap,wn.fog,wn.lights,{emissive:{value:new qt(0)},specular:{value:new qt(1118481)},shininess:{value:30}}]),vertexShader:bn.meshphong_vert,fragmentShader:bn.meshphong_frag},standard:{uniforms:en([wn.common,wn.envmap,wn.aomap,wn.lightmap,wn.emissivemap,wn.bumpmap,wn.normalmap,wn.displacementmap,wn.roughnessmap,wn.metalnessmap,wn.fog,wn.lights,{emissive:{value:new qt(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:bn.meshphysical_vert,fragmentShader:bn.meshphysical_frag},toon:{uniforms:en([wn.common,wn.aomap,wn.lightmap,wn.emissivemap,wn.bumpmap,wn.normalmap,wn.displacementmap,wn.gradientmap,wn.fog,wn.lights,{emissive:{value:new qt(0)}}]),vertexShader:bn.meshtoon_vert,fragmentShader:bn.meshtoon_frag},matcap:{uniforms:en([wn.common,wn.bumpmap,wn.normalmap,wn.displacementmap,wn.fog,{matcap:{value:null}}]),vertexShader:bn.meshmatcap_vert,fragmentShader:bn.meshmatcap_frag},points:{uniforms:en([wn.points,wn.fog]),vertexShader:bn.points_vert,fragmentShader:bn.points_frag},dashed:{uniforms:en([wn.common,wn.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:bn.linedashed_vert,fragmentShader:bn.linedashed_frag},depth:{uniforms:en([wn.common,wn.displacementmap]),vertexShader:bn.depth_vert,fragmentShader:bn.depth_frag},normal:{uniforms:en([wn.common,wn.bumpmap,wn.normalmap,wn.displacementmap,{opacity:{value:1}}]),vertexShader:bn.meshnormal_vert,fragmentShader:bn.meshnormal_frag},sprite:{uniforms:en([wn.sprite,wn.fog]),vertexShader:bn.sprite_vert,fragmentShader:bn.sprite_frag},background:{uniforms:{uvTransform:{value:new Rt},t2D:{value:null},backgroundIntensity:{value:1}},vertexShader:bn.background_vert,fragmentShader:bn.background_frag},backgroundCube:{uniforms:{envMap:{value:null},flipEnvMap:{value:-1},backgroundBlurriness:{value:0},backgroundIntensity:{value:1}},vertexShader:bn.backgroundCube_vert,fragmentShader:bn.backgroundCube_frag},cube:{uniforms:{tCube:{value:null},tFlip:{value:-1},opacity:{value:1}},vertexShader:bn.cube_vert,fragmentShader:bn.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:bn.equirect_vert,fragmentShader:bn.equirect_frag},distanceRGBA:{uniforms:en([wn.common,wn.displacementmap,{referencePosition:{value:new re},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:bn.distanceRGBA_vert,fragmentShader:bn.distanceRGBA_frag},shadow:{uniforms:en([wn.lights,wn.fog,{color:{value:new qt(0)},opacity:{value:1}}]),vertexShader:bn.shadow_vert,fragmentShader:bn.shadow_frag}};Sn.physical={uniforms:en([Sn.standard.uniforms,{clearcoat:{value:0},clearcoatMap:{value:null},clearcoatRoughness:{value:0},clearcoatRoughnessMap:{value:null},clearcoatNormalScale:{value:new Lt(1,1)},clearcoatNormalMap:{value:null},iridescence:{value:0},iridescenceMap:{value:null},iridescenceIOR:{value:1.3},iridescenceThicknessMinimum:{value:100},iridescenceThicknessMaximum:{value:400},iridescenceThicknessMap:{value:null},sheen:{value:0},sheenColor:{value:new qt(0)},sheenColorMap:{value:null},sheenRoughness:{value:1},sheenRoughnessMap:{value:null},transmission:{value:0},transmissionMap:{value:null},transmissionSamplerSize:{value:new Lt},transmissionSamplerMap:{value:null},thickness:{value:0},thicknessMap:{value:null},attenuationDistance:{value:0},attenuationColor:{value:new qt(0)},specularIntensity:{value:1},specularIntensityMap:{value:null},specularColor:{value:new qt(1,1,1)},specularColorMap:{value:null}}]),vertexShader:bn.meshphysical_vert,fragmentShader:bn.meshphysical_frag};const Tn={r:0,b:0,g:0};function An(t,e,i,n,r,s,a){const o=new qt(0);let c,h,u=!0===s?0:1,d=null,p=0,m=null;function f(e,i){e.getRGB(Tn,nn(t)),n.buffers.color.setClear(Tn.r,Tn.g,Tn.b,i,a)}return{getClearColor:function(){return o},setClearColor:function(t,e=1){o.set(t),u=e,f(o,u)},getClearAlpha:function(){return u},setClearAlpha:function(t){u=t,f(o,u)},render:function(n,s){let a=!1,g=!0===s.isScene?s.background:null;if(g&&g.isTexture){g=(s.backgroundBlurriness>0?i:e).get(g)}const v=t.xr,x=v.getSession&&v.getSession();x&&"additive"===x.environmentBlendMode&&(g=null),null===g?f(o,u):g&&g.isColor&&(f(g,1),a=!0),(t.autoClear||a)&&t.clear(t.autoClearColor,t.autoClearDepth,t.autoClearStencil),g&&(g.isCubeTexture||g.mapping===l)?(void 0===h&&(h=new Ki(new Qi(1e4,1e4,1e4),new sn({name:"BackgroundCubeMaterial",uniforms:tn(Sn.backgroundCube.uniforms),vertexShader:Sn.backgroundCube.vertexShader,fragmentShader:Sn.backgroundCube.fragmentShader,side:1,depthTest:!1,depthWrite:!1,fog:!1})),h.geometry.deleteAttribute("normal"),h.geometry.deleteAttribute("uv"),h.onBeforeRender=function(t,e,i){this.matrixWorld.copyPosition(i.matrixWorld)},Object.defineProperty(h.material,"envMap",{get:function(){return this.uniforms.envMap.value}}),r.update(h)),h.material.uniforms.envMap.value=g,h.material.uniforms.flipEnvMap.value=g.isCubeTexture&&!1===g.isRenderTargetTexture?-1:1,h.material.uniforms.backgroundBlurriness.value=s.backgroundBlurriness,h.material.uniforms.backgroundIntensity.value=s.backgroundIntensity,d===g&&p===g.version&&m===t.toneMapping||(h.material.needsUpdate=!0,d=g,p=g.version,m=t.toneMapping),h.layers.enableAll(),n.unshift(h,h.geometry,h.material,0,0,null)):g&&g.isTexture&&(void 0===c&&(c=new Ki(new Mn(2,2),new sn({name:"BackgroundMaterial",uniforms:tn(Sn.background.uniforms),vertexShader:Sn.background.vertexShader,fragmentShader:Sn.background.fragmentShader,side:0,depthTest:!1,depthWrite:!1,fog:!1})),c.geometry.deleteAttribute("normal"),Object.defineProperty(c.material,"map",{get:function(){return this.uniforms.t2D.value}}),r.update(c)),c.material.uniforms.t2D.value=g,c.material.uniforms.backgroundIntensity.value=s.backgroundIntensity,!0===g.matrixAutoUpdate&&g.updateMatrix(),c.material.uniforms.uvTransform.value.copy(g.matrix),d===g&&p===g.version&&m===t.toneMapping||(c.material.needsUpdate=!0,d=g,p=g.version,m=t.toneMapping),c.layers.enableAll(),n.unshift(c,c.geometry,c.material,0,0,null))}}}function En(t,e,i,n){const r=t.getParameter(34921),s=n.isWebGL2?null:e.get("OES_vertex_array_object"),a=n.isWebGL2||null!==s,o={},l=p(null);let c=l,h=!1;function u(e){return n.isWebGL2?t.bindVertexArray(e):s.bindVertexArrayOES(e)}function d(e){return n.isWebGL2?t.deleteVertexArray(e):s.deleteVertexArrayOES(e)}function p(t){const e=[],i=[],n=[];for(let t=0;t=0){const i=r[e];let n=s[e];if(void 0===n&&("instanceMatrix"===e&&t.instanceMatrix&&(n=t.instanceMatrix),"instanceColor"===e&&t.instanceColor&&(n=t.instanceColor)),void 0===i)return!0;if(i.attribute!==n)return!0;if(n&&i.data!==n.data)return!0;a++}}return c.attributesNum!==a||c.index!==n}(r,_,d,y),M&&function(t,e,i,n){const r={},s=e.attributes;let a=0;const o=i.getAttributes();for(const e in o){if(o[e].location>=0){let i=s[e];void 0===i&&("instanceMatrix"===e&&t.instanceMatrix&&(i=t.instanceMatrix),"instanceColor"===e&&t.instanceColor&&(i=t.instanceColor));const n={};n.attribute=i,i&&i.data&&(n.data=i.data),r[e]=n,a++}}c.attributes=r,c.attributesNum=a,c.index=n}(r,_,d,y)}else{const t=!0===l.wireframe;c.geometry===_.id&&c.program===d.id&&c.wireframe===t||(c.geometry=_.id,c.program=d.id,c.wireframe=t,M=!0)}null!==y&&i.update(y,34963),(M||h)&&(h=!1,function(r,s,a,o){if(!1===n.isWebGL2&&(r.isInstancedMesh||o.isInstancedBufferGeometry)&&null===e.get("ANGLE_instanced_arrays"))return;m();const l=o.attributes,c=a.getAttributes(),h=s.defaultAttributeValues;for(const e in c){const n=c[e];if(n.location>=0){let s=l[e];if(void 0===s&&("instanceMatrix"===e&&r.instanceMatrix&&(s=r.instanceMatrix),"instanceColor"===e&&r.instanceColor&&(s=r.instanceColor)),void 0!==s){const e=s.normalized,a=s.itemSize,l=i.get(s);if(void 0===l)continue;const c=l.buffer,h=l.type,u=l.bytesPerElement;if(s.isInterleavedBufferAttribute){const i=s.data,l=i.stride,d=s.offset;if(i.isInstancedInterleavedBuffer){for(let t=0;t0&&t.getShaderPrecisionFormat(35632,36338).precision>0)return"highp";e="mediump"}return"mediump"===e&&t.getShaderPrecisionFormat(35633,36337).precision>0&&t.getShaderPrecisionFormat(35632,36337).precision>0?"mediump":"lowp"}const s="undefined"!=typeof WebGL2RenderingContext&&t instanceof WebGL2RenderingContext||"undefined"!=typeof WebGL2ComputeRenderingContext&&t instanceof WebGL2ComputeRenderingContext;let a=void 0!==i.precision?i.precision:"highp";const o=r(a);o!==a&&(console.warn("THREE.WebGLRenderer:",a,"not supported, using",o,"instead."),a=o);const l=s||e.has("WEBGL_draw_buffers"),c=!0===i.logarithmicDepthBuffer,h=t.getParameter(34930),u=t.getParameter(35660),d=t.getParameter(3379),p=t.getParameter(34076),m=t.getParameter(34921),f=t.getParameter(36347),g=t.getParameter(36348),v=t.getParameter(36349),x=u>0,_=s||e.has("OES_texture_float");return{isWebGL2:s,drawBuffers:l,getMaxAnisotropy:function(){if(void 0!==n)return n;if(!0===e.has("EXT_texture_filter_anisotropic")){const i=e.get("EXT_texture_filter_anisotropic");n=t.getParameter(i.MAX_TEXTURE_MAX_ANISOTROPY_EXT)}else n=0;return n},getMaxPrecision:r,precision:a,logarithmicDepthBuffer:c,maxTextures:h,maxVertexTextures:u,maxTextureSize:d,maxCubemapSize:p,maxAttributes:m,maxVertexUniforms:f,maxVaryings:g,maxFragmentUniforms:v,vertexTextures:x,floatFragmentTextures:_,floatVertexTextures:x&&_,maxSamples:s?t.getParameter(36183):0}}function Rn(t){const e=this;let i=null,n=0,r=!1,s=!1;const a=new fn,o=new Rt,l={value:null,needsUpdate:!1};function c(){l.value!==i&&(l.value=i,l.needsUpdate=n>0),e.numPlanes=n,e.numIntersection=0}function h(t,i,n,r){const s=null!==t?t.length:0;let c=null;if(0!==s){if(c=l.value,!0!==r||null===c){const e=n+4*s,r=i.matrixWorldInverse;o.getNormalMatrix(r),(null===c||c.length0){const a=new un(s.height/2);return a.fromEquirectangularTexture(t,r),e.set(r,a),r.addEventListener("dispose",n),i(a.texture,r.mapping)}return null}}}return r},dispose:function(){e=new WeakMap}}}class In extends an{constructor(t=-1,e=1,i=1,n=-1,r=.1,s=2e3){super(),this.isOrthographicCamera=!0,this.type="OrthographicCamera",this.zoom=1,this.view=null,this.left=t,this.right=e,this.top=i,this.bottom=n,this.near=r,this.far=s,this.updateProjectionMatrix()}copy(t,e){return super.copy(t,e),this.left=t.left,this.right=t.right,this.top=t.top,this.bottom=t.bottom,this.near=t.near,this.far=t.far,this.zoom=t.zoom,this.view=null===t.view?null:Object.assign({},t.view),this}setViewOffset(t,e,i,n,r,s){null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=i,this.view.offsetY=n,this.view.width=r,this.view.height=s,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const t=(this.right-this.left)/(2*this.zoom),e=(this.top-this.bottom)/(2*this.zoom),i=(this.right+this.left)/2,n=(this.top+this.bottom)/2;let r=i-t,s=i+t,a=n+e,o=n-e;if(null!==this.view&&this.view.enabled){const t=(this.right-this.left)/this.view.fullWidth/this.zoom,e=(this.top-this.bottom)/this.view.fullHeight/this.zoom;r+=t*this.view.offsetX,s=r+t*this.view.width,a-=e*this.view.offsetY,o=a-e*this.view.height}this.projectionMatrix.makeOrthographic(r,s,a,o,this.near,this.far),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(t){const e=super.toJSON(t);return e.object.zoom=this.zoom,e.object.left=this.left,e.object.right=this.right,e.object.top=this.top,e.object.bottom=this.bottom,e.object.near=this.near,e.object.far=this.far,null!==this.view&&(e.object.view=Object.assign({},this.view)),e}}const Dn=[.125,.215,.35,.446,.526,.582],Nn=20,On=new In,zn=new qt;let Un=null;const Bn=(1+Math.sqrt(5))/2,Fn=1/Bn,kn=[new re(1,1,1),new re(-1,1,1),new re(1,1,-1),new re(-1,1,-1),new re(0,Bn,Fn),new re(0,Bn,-Fn),new re(Fn,0,Bn),new re(-Fn,0,Bn),new re(Bn,Fn,0),new re(-Bn,Fn,0)];class Gn{constructor(t){this._renderer=t,this._pingPongRenderTarget=null,this._lodMax=0,this._cubeSize=0,this._lodPlanes=[],this._sizeLods=[],this._sigmas=[],this._blurMaterial=null,this._cubemapMaterial=null,this._equirectMaterial=null,this._compileMaterial(this._blurMaterial)}fromScene(t,e=0,i=.1,n=100){Un=this._renderer.getRenderTarget(),this._setSize(256);const r=this._allocateTargets();return r.depthBuffer=!0,this._sceneToCubeUV(t,i,n,r),e>0&&this._blur(r,0,0,e),this._applyPMREM(r),this._cleanup(r),r}fromEquirectangular(t,e=null){return this._fromTexture(t,e)}fromCubemap(t,e=null){return this._fromTexture(t,e)}compileCubemapShader(){null===this._cubemapMaterial&&(this._cubemapMaterial=jn(),this._compileMaterial(this._cubemapMaterial))}compileEquirectangularShader(){null===this._equirectMaterial&&(this._equirectMaterial=Wn(),this._compileMaterial(this._equirectMaterial))}dispose(){this._dispose(),null!==this._cubemapMaterial&&this._cubemapMaterial.dispose(),null!==this._equirectMaterial&&this._equirectMaterial.dispose()}_setSize(t){this._lodMax=Math.floor(Math.log2(t)),this._cubeSize=Math.pow(2,this._lodMax)}_dispose(){null!==this._blurMaterial&&this._blurMaterial.dispose(),null!==this._pingPongRenderTarget&&this._pingPongRenderTarget.dispose();for(let t=0;tt-4?o=Dn[a-t+4-1]:0===a&&(o=0),n.push(o);const l=1/(s-2),c=-l,h=1+l,u=[c,c,h,c,h,h,c,c,h,h,c,h],d=6,p=6,m=3,f=2,g=1,v=new Float32Array(m*p*d),x=new Float32Array(f*p*d),_=new Float32Array(g*p*d);for(let t=0;t2?0:-1,n=[e,i,0,e+2/3,i,0,e+2/3,i+1,0,e,i,0,e+2/3,i+1,0,e,i+1,0];v.set(n,m*p*t),x.set(u,f*p*t);const r=[t,t,t,t,t,t];_.set(r,g*p*t)}const y=new Di;y.setAttribute("position",new bi(v,m)),y.setAttribute("uv",new bi(x,f)),y.setAttribute("faceIndex",new bi(_,g)),e.push(y),r>4&&r--}return{lodPlanes:e,sizeLods:i,sigmas:n}}(n)),this._blurMaterial=function(t,e,i){const n=new Float32Array(Nn),r=new re(0,1,0);return new sn({name:"SphericalGaussianBlur",defines:{n:Nn,CUBEUV_TEXEL_WIDTH:1/e,CUBEUV_TEXEL_HEIGHT:1/i,CUBEUV_MAX_MIP:`${t}.0`},uniforms:{envMap:{value:null},samples:{value:1},weights:{value:n},latitudinal:{value:!1},dTheta:{value:0},mipInt:{value:0},poleAxis:{value:r}},vertexShader:qn(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\t\t\tuniform int samples;\n\t\t\tuniform float weights[ n ];\n\t\t\tuniform bool latitudinal;\n\t\t\tuniform float dTheta;\n\t\t\tuniform float mipInt;\n\t\t\tuniform vec3 poleAxis;\n\n\t\t\t#define ENVMAP_TYPE_CUBE_UV\n\t\t\t#include \n\n\t\t\tvec3 getSample( float theta, vec3 axis ) {\n\n\t\t\t\tfloat cosTheta = cos( theta );\n\t\t\t\t// Rodrigues' axis-angle rotation\n\t\t\t\tvec3 sampleDirection = vOutputDirection * cosTheta\n\t\t\t\t\t+ cross( axis, vOutputDirection ) * sin( theta )\n\t\t\t\t\t+ axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta );\n\n\t\t\t\treturn bilinearCubeUV( envMap, sampleDirection, mipInt );\n\n\t\t\t}\n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection );\n\n\t\t\t\tif ( all( equal( axis, vec3( 0.0 ) ) ) ) {\n\n\t\t\t\t\taxis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x );\n\n\t\t\t\t}\n\n\t\t\t\taxis = normalize( axis );\n\n\t\t\t\tgl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t\t\t\tgl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis );\n\n\t\t\t\tfor ( int i = 1; i < n; i++ ) {\n\n\t\t\t\t\tif ( i >= samples ) {\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tfloat theta = dTheta * float( i );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( theta, axis );\n\n\t\t\t\t}\n\n\t\t\t}\n\t\t",blending:0,depthTest:!1,depthWrite:!1})}(n,t,e)}return n}_compileMaterial(t){const e=new Ki(this._lodPlanes[0],t);this._renderer.compile(e,On)}_sceneToCubeUV(t,e,i,n){const r=new on(90,1,e,i),s=[1,-1,1,1,1,1],a=[1,1,1,-1,-1,-1],o=this._renderer,l=o.autoClear,c=o.toneMapping;o.getClearColor(zn),o.toneMapping=0,o.autoClear=!1;const h=new _i({name:"PMREM.Background",side:1,depthWrite:!1,depthTest:!1}),u=new Ki(new Qi,h);let d=!1;const p=t.background;p?p.isColor&&(h.color.copy(p),t.background=null,d=!0):(h.color.copy(zn),d=!0);for(let e=0;e<6;e++){const i=e%3;0===i?(r.up.set(0,s[e],0),r.lookAt(a[e],0,0)):1===i?(r.up.set(0,0,s[e]),r.lookAt(0,a[e],0)):(r.up.set(0,s[e],0),r.lookAt(0,0,a[e]));const l=this._cubeSize;Hn(n,i*l,e>2?l:0,l,l),o.setRenderTarget(n),d&&o.render(u,r),o.render(t,r)}u.geometry.dispose(),u.material.dispose(),o.toneMapping=c,o.autoClear=l,t.background=p}_textureToCubeUV(t,e){const i=this._renderer,n=t.mapping===r||t.mapping===s;n?(null===this._cubemapMaterial&&(this._cubemapMaterial=jn()),this._cubemapMaterial.uniforms.flipEnvMap.value=!1===t.isRenderTargetTexture?-1:1):null===this._equirectMaterial&&(this._equirectMaterial=Wn());const a=n?this._cubemapMaterial:this._equirectMaterial,o=new Ki(this._lodPlanes[0],a);a.uniforms.envMap.value=t;const l=this._cubeSize;Hn(e,0,0,3*l,2*l),i.setRenderTarget(e),i.render(o,On)}_applyPMREM(t){const e=this._renderer,i=e.autoClear;e.autoClear=!1;for(let e=1;eNn&&console.warn(`sigmaRadians, ${r}, is too large and will clip, as it requested ${m} samples when the maximum is set to 20`);const f=[];let g=0;for(let t=0;tv-4?n-v+4:0),4*(this._cubeSize-x),3*x,2*x),o.setRenderTarget(e),o.render(c,On)}}function Vn(t,e,i){const n=new te(t,e,i);return n.texture.mapping=l,n.texture.name="PMREM.cubeUv",n.scissorTest=!0,n}function Hn(t,e,i,n,r){t.viewport.set(e,i,n,r),t.scissor.set(e,i,n,r)}function Wn(){return new sn({name:"EquirectangularToCubeUV",uniforms:{envMap:{value:null}},vertexShader:qn(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\n\t\t\t#include \n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 outputDirection = normalize( vOutputDirection );\n\t\t\t\tvec2 uv = equirectUv( outputDirection );\n\n\t\t\t\tgl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 );\n\n\t\t\t}\n\t\t",blending:0,depthTest:!1,depthWrite:!1})}function jn(){return new sn({name:"CubemapToCubeUV",uniforms:{envMap:{value:null},flipEnvMap:{value:-1}},vertexShader:qn(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tuniform float flipEnvMap;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform samplerCube envMap;\n\n\t\t\tvoid main() {\n\n\t\t\t\tgl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) );\n\n\t\t\t}\n\t\t",blending:0,depthTest:!1,depthWrite:!1})}function qn(){return"\n\n\t\tprecision mediump float;\n\t\tprecision mediump int;\n\n\t\tattribute float faceIndex;\n\n\t\tvarying vec3 vOutputDirection;\n\n\t\t// RH coordinate system; PMREM face-indexing convention\n\t\tvec3 getDirection( vec2 uv, float face ) {\n\n\t\t\tuv = 2.0 * uv - 1.0;\n\n\t\t\tvec3 direction = vec3( uv, 1.0 );\n\n\t\t\tif ( face == 0.0 ) {\n\n\t\t\t\tdirection = direction.zyx; // ( 1, v, u ) pos x\n\n\t\t\t} else if ( face == 1.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xz *= -1.0; // ( -u, 1, -v ) pos y\n\n\t\t\t} else if ( face == 2.0 ) {\n\n\t\t\t\tdirection.x *= -1.0; // ( -u, v, 1 ) pos z\n\n\t\t\t} else if ( face == 3.0 ) {\n\n\t\t\t\tdirection = direction.zyx;\n\t\t\t\tdirection.xz *= -1.0; // ( -1, v, -u ) neg x\n\n\t\t\t} else if ( face == 4.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xy *= -1.0; // ( -u, -1, v ) neg y\n\n\t\t\t} else if ( face == 5.0 ) {\n\n\t\t\t\tdirection.z *= -1.0; // ( u, v, -1 ) neg z\n\n\t\t\t}\n\n\t\t\treturn direction;\n\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tvOutputDirection = getDirection( uv, faceIndex );\n\t\t\tgl_Position = vec4( position, 1.0 );\n\n\t\t}\n\t"}function Xn(t){let e=new WeakMap,i=null;function n(t){const i=t.target;i.removeEventListener("dispose",n);const r=e.get(i);void 0!==r&&(e.delete(i),r.dispose())}return{get:function(l){if(l&&l.isTexture){const c=l.mapping,h=c===a||c===o,u=c===r||c===s;if(h||u){if(l.isRenderTargetTexture&&!0===l.needsPMREMUpdate){l.needsPMREMUpdate=!1;let n=e.get(l);return null===i&&(i=new Gn(t)),n=h?i.fromEquirectangular(l,n):i.fromCubemap(l,n),e.set(l,n),n.texture}if(e.has(l))return e.get(l).texture;{const r=l.image;if(h&&r&&r.height>0||u&&r&&function(t){let e=0;const i=6;for(let n=0;ne.maxTextureSize&&(E=Math.ceil(A/e.maxTextureSize),A=e.maxTextureSize);const C=new Float32Array(A*E*4*m),L=new ee(C,A,E,m);L.type=M,L.needsUpdate=!0;const R=4*T;for(let I=0;I0)return t;const r=e*i;let s=ar[r];if(void 0===s&&(s=new Float32Array(r),ar[r]=s),0!==e){n.toArray(s,0);for(let n=1,r=0;n!==e;++n)r+=i,t[n].toArray(s,r)}return s}function dr(t,e){if(t.length!==e.length)return!1;for(let i=0,n=t.length;i":" "} ${r}: ${i[t]}`)}return n.join("\n")}(t.getShaderSource(e),n)}return r}function cs(t,e){const i=function(t){switch(t){case at:return["Linear","( value )"];case ot:return["sRGB","( value )"];default:return console.warn("THREE.WebGLProgram: Unsupported encoding:",t),["Linear","( value )"]}}(e);return"vec4 "+t+"( vec4 value ) { return LinearTo"+i[0]+i[1]+"; }"}function hs(t,e){let i;switch(e){case 1:i="Linear";break;case 2:i="Reinhard";break;case 3:i="OptimizedCineon";break;case 4:i="ACESFilmic";break;case 5:i="Custom";break;default:console.warn("THREE.WebGLProgram: Unsupported toneMapping:",e),i="Linear"}return"vec3 "+t+"( vec3 color ) { return "+i+"ToneMapping( color ); }"}function us(t){return""!==t}function ds(t,e){const i=e.numSpotLightShadows+e.numSpotLightMaps-e.numSpotLightShadowsWithMaps;return t.replace(/NUM_DIR_LIGHTS/g,e.numDirLights).replace(/NUM_SPOT_LIGHTS/g,e.numSpotLights).replace(/NUM_SPOT_LIGHT_MAPS/g,e.numSpotLightMaps).replace(/NUM_SPOT_LIGHT_COORDS/g,i).replace(/NUM_RECT_AREA_LIGHTS/g,e.numRectAreaLights).replace(/NUM_POINT_LIGHTS/g,e.numPointLights).replace(/NUM_HEMI_LIGHTS/g,e.numHemiLights).replace(/NUM_DIR_LIGHT_SHADOWS/g,e.numDirLightShadows).replace(/NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS/g,e.numSpotLightShadowsWithMaps).replace(/NUM_SPOT_LIGHT_SHADOWS/g,e.numSpotLightShadows).replace(/NUM_POINT_LIGHT_SHADOWS/g,e.numPointLightShadows)}function ps(t,e){return t.replace(/NUM_CLIPPING_PLANES/g,e.numClippingPlanes).replace(/UNION_CLIPPING_PLANES/g,e.numClippingPlanes-e.numClipIntersection)}const ms=/^[ \t]*#include +<([\w\d./]+)>/gm;function fs(t){return t.replace(ms,gs)}function gs(t,e){const i=bn[e];if(void 0===i)throw new Error("Can not resolve #include <"+e+">");return fs(i)}const vs=/#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*<\s*(\d+)\s*;\s*i\s*\+\+\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g;function xs(t){return t.replace(vs,_s)}function _s(t,e,i,n){let r="";for(let t=parseInt(e);t0&&(_+="\n"),y=[g,v].filter(us).join("\n"),y.length>0&&(y+="\n")):(_=[ys(i),"#define SHADER_NAME "+i.shaderName,v,i.instancing?"#define USE_INSTANCING":"",i.instancingColor?"#define USE_INSTANCING_COLOR":"",i.supportsVertexTextures?"#define VERTEX_TEXTURES":"",i.useFog&&i.fog?"#define USE_FOG":"",i.useFog&&i.fogExp2?"#define FOG_EXP2":"",i.map?"#define USE_MAP":"",i.envMap?"#define USE_ENVMAP":"",i.envMap?"#define "+p:"",i.lightMap?"#define USE_LIGHTMAP":"",i.aoMap?"#define USE_AOMAP":"",i.emissiveMap?"#define USE_EMISSIVEMAP":"",i.bumpMap?"#define USE_BUMPMAP":"",i.normalMap?"#define USE_NORMALMAP":"",i.normalMap&&i.objectSpaceNormalMap?"#define OBJECTSPACE_NORMALMAP":"",i.normalMap&&i.tangentSpaceNormalMap?"#define TANGENTSPACE_NORMALMAP":"",i.clearcoatMap?"#define USE_CLEARCOATMAP":"",i.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",i.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",i.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",i.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",i.displacementMap&&i.supportsVertexTextures?"#define USE_DISPLACEMENTMAP":"",i.specularMap?"#define USE_SPECULARMAP":"",i.specularIntensityMap?"#define USE_SPECULARINTENSITYMAP":"",i.specularColorMap?"#define USE_SPECULARCOLORMAP":"",i.roughnessMap?"#define USE_ROUGHNESSMAP":"",i.metalnessMap?"#define USE_METALNESSMAP":"",i.alphaMap?"#define USE_ALPHAMAP":"",i.transmission?"#define USE_TRANSMISSION":"",i.transmissionMap?"#define USE_TRANSMISSIONMAP":"",i.thicknessMap?"#define USE_THICKNESSMAP":"",i.sheenColorMap?"#define USE_SHEENCOLORMAP":"",i.sheenRoughnessMap?"#define USE_SHEENROUGHNESSMAP":"",i.vertexTangents?"#define USE_TANGENT":"",i.vertexColors?"#define USE_COLOR":"",i.vertexAlphas?"#define USE_COLOR_ALPHA":"",i.vertexUvs?"#define USE_UV":"",i.uvsVertexOnly?"#define UVS_VERTEX_ONLY":"",i.flatShading?"#define FLAT_SHADED":"",i.skinning?"#define USE_SKINNING":"",i.morphTargets?"#define USE_MORPHTARGETS":"",i.morphNormals&&!1===i.flatShading?"#define USE_MORPHNORMALS":"",i.morphColors&&i.isWebGL2?"#define USE_MORPHCOLORS":"",i.morphTargetsCount>0&&i.isWebGL2?"#define MORPHTARGETS_TEXTURE":"",i.morphTargetsCount>0&&i.isWebGL2?"#define MORPHTARGETS_TEXTURE_STRIDE "+i.morphTextureStride:"",i.morphTargetsCount>0&&i.isWebGL2?"#define MORPHTARGETS_COUNT "+i.morphTargetsCount:"",i.doubleSided?"#define DOUBLE_SIDED":"",i.flipSided?"#define FLIP_SIDED":"",i.shadowMapEnabled?"#define USE_SHADOWMAP":"",i.shadowMapEnabled?"#define "+u:"",i.sizeAttenuation?"#define USE_SIZEATTENUATION":"",i.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",i.logarithmicDepthBuffer&&i.rendererExtensionFragDepth?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;","#ifdef USE_INSTANCING","\tattribute mat4 instanceMatrix;","#endif","#ifdef USE_INSTANCING_COLOR","\tattribute vec3 instanceColor;","#endif","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_TANGENT","\tattribute vec4 tangent;","#endif","#if defined( USE_COLOR_ALPHA )","\tattribute vec4 color;","#elif defined( USE_COLOR )","\tattribute vec3 color;","#endif","#if ( defined( USE_MORPHTARGETS ) && ! defined( MORPHTARGETS_TEXTURE ) )","\tattribute vec3 morphTarget0;","\tattribute vec3 morphTarget1;","\tattribute vec3 morphTarget2;","\tattribute vec3 morphTarget3;","\t#ifdef USE_MORPHNORMALS","\t\tattribute vec3 morphNormal0;","\t\tattribute vec3 morphNormal1;","\t\tattribute vec3 morphNormal2;","\t\tattribute vec3 morphNormal3;","\t#else","\t\tattribute vec3 morphTarget4;","\t\tattribute vec3 morphTarget5;","\t\tattribute vec3 morphTarget6;","\t\tattribute vec3 morphTarget7;","\t#endif","#endif","#ifdef USE_SKINNING","\tattribute vec4 skinIndex;","\tattribute vec4 skinWeight;","#endif","\n"].filter(us).join("\n"),y=[g,ys(i),"#define SHADER_NAME "+i.shaderName,v,i.useFog&&i.fog?"#define USE_FOG":"",i.useFog&&i.fogExp2?"#define FOG_EXP2":"",i.map?"#define USE_MAP":"",i.matcap?"#define USE_MATCAP":"",i.envMap?"#define USE_ENVMAP":"",i.envMap?"#define "+d:"",i.envMap?"#define "+p:"",i.envMap?"#define "+m:"",f?"#define CUBEUV_TEXEL_WIDTH "+f.texelWidth:"",f?"#define CUBEUV_TEXEL_HEIGHT "+f.texelHeight:"",f?"#define CUBEUV_MAX_MIP "+f.maxMip+".0":"",i.lightMap?"#define USE_LIGHTMAP":"",i.aoMap?"#define USE_AOMAP":"",i.emissiveMap?"#define USE_EMISSIVEMAP":"",i.bumpMap?"#define USE_BUMPMAP":"",i.normalMap?"#define USE_NORMALMAP":"",i.normalMap&&i.objectSpaceNormalMap?"#define OBJECTSPACE_NORMALMAP":"",i.normalMap&&i.tangentSpaceNormalMap?"#define TANGENTSPACE_NORMALMAP":"",i.clearcoat?"#define USE_CLEARCOAT":"",i.clearcoatMap?"#define USE_CLEARCOATMAP":"",i.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",i.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",i.iridescence?"#define USE_IRIDESCENCE":"",i.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",i.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",i.specularMap?"#define USE_SPECULARMAP":"",i.specularIntensityMap?"#define USE_SPECULARINTENSITYMAP":"",i.specularColorMap?"#define USE_SPECULARCOLORMAP":"",i.roughnessMap?"#define USE_ROUGHNESSMAP":"",i.metalnessMap?"#define USE_METALNESSMAP":"",i.alphaMap?"#define USE_ALPHAMAP":"",i.alphaTest?"#define USE_ALPHATEST":"",i.sheen?"#define USE_SHEEN":"",i.sheenColorMap?"#define USE_SHEENCOLORMAP":"",i.sheenRoughnessMap?"#define USE_SHEENROUGHNESSMAP":"",i.transmission?"#define USE_TRANSMISSION":"",i.transmissionMap?"#define USE_TRANSMISSIONMAP":"",i.thicknessMap?"#define USE_THICKNESSMAP":"",i.decodeVideoTexture?"#define DECODE_VIDEO_TEXTURE":"",i.vertexTangents?"#define USE_TANGENT":"",i.vertexColors||i.instancingColor?"#define USE_COLOR":"",i.vertexAlphas?"#define USE_COLOR_ALPHA":"",i.vertexUvs?"#define USE_UV":"",i.uvsVertexOnly?"#define UVS_VERTEX_ONLY":"",i.gradientMap?"#define USE_GRADIENTMAP":"",i.flatShading?"#define FLAT_SHADED":"",i.doubleSided?"#define DOUBLE_SIDED":"",i.flipSided?"#define FLIP_SIDED":"",i.shadowMapEnabled?"#define USE_SHADOWMAP":"",i.shadowMapEnabled?"#define "+u:"",i.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",i.physicallyCorrectLights?"#define PHYSICALLY_CORRECT_LIGHTS":"",i.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",i.logarithmicDepthBuffer&&i.rendererExtensionFragDepth?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;",0!==i.toneMapping?"#define TONE_MAPPING":"",0!==i.toneMapping?bn.tonemapping_pars_fragment:"",0!==i.toneMapping?hs("toneMapping",i.toneMapping):"",i.dithering?"#define DITHERING":"",i.opaque?"#define OPAQUE":"",bn.encodings_pars_fragment,cs("linearToOutputTexel",i.outputEncoding),i.useDepthPacking?"#define DEPTH_PACKING "+i.depthPacking:"","\n"].filter(us).join("\n")),c=fs(c),c=ds(c,i),c=ps(c,i),h=fs(h),h=ds(h,i),h=ps(h,i),c=xs(c),h=xs(h),i.isWebGL2&&!0!==i.isRawShaderMaterial&&(M="#version 300 es\n",_=["precision mediump sampler2DArray;","#define attribute in","#define varying out","#define texture2D texture"].join("\n")+"\n"+_,y=["#define varying in",i.glslVersion===dt?"":"layout(location = 0) out highp vec4 pc_fragColor;",i.glslVersion===dt?"":"#define gl_FragColor pc_fragColor","#define gl_FragDepthEXT gl_FragDepth","#define texture2D texture","#define textureCube texture","#define texture2DProj textureProj","#define texture2DLodEXT textureLod","#define texture2DProjLodEXT textureProjLod","#define textureCubeLodEXT textureLod","#define texture2DGradEXT textureGrad","#define texture2DProjGradEXT textureProjGrad","#define textureCubeGradEXT textureGrad"].join("\n")+"\n"+y,b>0&&(_=["#extension GL_OVR_multiview : require","layout(num_views = "+b+") in;","#define VIEW_ID gl_ViewID_OVR"].join("\n")+"\n"+_,_=_.replace(["uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;"].join("\n"),["uniform mat4 modelViewMatrices["+b+"];","uniform mat4 projectionMatrices["+b+"];","uniform mat4 viewMatrices["+b+"];","uniform mat3 normalMatrices["+b+"];","#define modelViewMatrix modelViewMatrices[VIEW_ID]","#define projectionMatrix projectionMatrices[VIEW_ID]","#define viewMatrix viewMatrices[VIEW_ID]","#define normalMatrix normalMatrices[VIEW_ID]"].join("\n")),y=["#extension GL_OVR_multiview : require","#define VIEW_ID gl_ViewID_OVR"].join("\n")+"\n"+y,y=y.replace("uniform mat4 viewMatrix;",["uniform mat4 viewMatrices["+b+"];","#define viewMatrix viewMatrices[VIEW_ID]"].join("\n"))));const w=M+y+h,S=as(a,35633,M+_+c),T=as(a,35632,w);if(a.attachShader(x,S),a.attachShader(x,T),void 0!==i.index0AttributeName?a.bindAttribLocation(x,0,i.index0AttributeName):!0===i.morphTargets&&a.bindAttribLocation(x,0,"position"),a.linkProgram(x),t.debug.checkShaderErrors){const t=a.getProgramInfoLog(x).trim(),e=a.getShaderInfoLog(S).trim(),i=a.getShaderInfoLog(T).trim();let n=!0,r=!0;if(!1===a.getProgramParameter(x,35714)){n=!1;const e=ls(a,S,"vertex"),i=ls(a,T,"fragment");console.error("THREE.WebGLProgram: Shader Error "+a.getError()+" - VALIDATE_STATUS "+a.getProgramParameter(x,35715)+"\n\nProgram Info Log: "+t+"\n"+e+"\n"+i)}else""!==t?console.warn("THREE.WebGLProgram: Program Info Log:",t):""!==e&&""!==i||(r=!1);r&&(this.diagnostics={runnable:n,programLog:t,vertexShader:{log:e,prefix:_},fragmentShader:{log:i,prefix:y}})}let A,E;return a.deleteShader(S),a.deleteShader(T),this.getUniforms=function(){return void 0===A&&(A=new ss(a,x)),A},this.getAttributes=function(){return void 0===E&&(E=function(t,e){const i={},n=t.getProgramParameter(e,35721);for(let r=0;r0,N=s.clearcoat>0,O=s.iridescence>0;return{isWebGL2:u,shaderID:w,shaderName:s.type,vertexShader:A,fragmentShader:E,defines:s.defines,customVertexShaderID:C,customFragmentShaderID:L,isRawShaderMaterial:!0===s.isRawShaderMaterial,glslVersion:s.glslVersion,precision:m,instancing:!0===v.isInstancedMesh,instancingColor:!0===v.isInstancedMesh&&null!==v.instanceColor,supportsVertexTextures:p,numMultiviewViews:I,outputEncoding:null===P?t.outputEncoding:!0===P.isXRRenderTarget?P.texture.encoding:at,map:!!s.map,matcap:!!s.matcap,envMap:!!M,envMapMode:M&&M.mapping,envMapCubeUVHeight:b,lightMap:!!s.lightMap,aoMap:!!s.aoMap,emissiveMap:!!s.emissiveMap,bumpMap:!!s.bumpMap,normalMap:!!s.normalMap,objectSpaceNormalMap:1===s.normalMapType,tangentSpaceNormalMap:0===s.normalMapType,decodeVideoTexture:!!s.map&&!0===s.map.isVideoTexture&&s.map.encoding===ot,clearcoat:N,clearcoatMap:N&&!!s.clearcoatMap,clearcoatRoughnessMap:N&&!!s.clearcoatRoughnessMap,clearcoatNormalMap:N&&!!s.clearcoatNormalMap,iridescence:O,iridescenceMap:O&&!!s.iridescenceMap,iridescenceThicknessMap:O&&!!s.iridescenceThicknessMap,displacementMap:!!s.displacementMap,roughnessMap:!!s.roughnessMap,metalnessMap:!!s.metalnessMap,specularMap:!!s.specularMap,specularIntensityMap:!!s.specularIntensityMap,specularColorMap:!!s.specularColorMap,opaque:!1===s.transparent&&1===s.blending,alphaMap:!!s.alphaMap,alphaTest:D,gradientMap:!!s.gradientMap,sheen:s.sheen>0,sheenColorMap:!!s.sheenColorMap,sheenRoughnessMap:!!s.sheenRoughnessMap,transmission:s.transmission>0,transmissionMap:!!s.transmissionMap,thicknessMap:!!s.thicknessMap,combine:s.combine,vertexTangents:!!s.normalMap&&!!_.attributes.tangent,vertexColors:s.vertexColors,vertexAlphas:!0===s.vertexColors&&!!_.attributes.color&&4===_.attributes.color.itemSize,vertexUvs:!!(s.map||s.bumpMap||s.normalMap||s.specularMap||s.alphaMap||s.emissiveMap||s.roughnessMap||s.metalnessMap||s.clearcoatMap||s.clearcoatRoughnessMap||s.clearcoatNormalMap||s.iridescenceMap||s.iridescenceThicknessMap||s.displacementMap||s.transmissionMap||s.thicknessMap||s.specularIntensityMap||s.specularColorMap||s.sheenColorMap||s.sheenRoughnessMap),uvsVertexOnly:!(s.map||s.bumpMap||s.normalMap||s.specularMap||s.alphaMap||s.emissiveMap||s.roughnessMap||s.metalnessMap||s.clearcoatNormalMap||s.iridescenceMap||s.iridescenceThicknessMap||s.transmission>0||s.transmissionMap||s.thicknessMap||s.specularIntensityMap||s.specularColorMap||s.sheen>0||s.sheenColorMap||s.sheenRoughnessMap||!s.displacementMap),fog:!!x,useFog:!0===s.fog,fogExp2:x&&x.isFogExp2,flatShading:!!s.flatShading,sizeAttenuation:s.sizeAttenuation,logarithmicDepthBuffer:d,skinning:!0===v.isSkinnedMesh,morphTargets:void 0!==_.morphAttributes.position,morphNormals:void 0!==_.morphAttributes.normal,morphColors:void 0!==_.morphAttributes.color,morphTargetsCount:T,morphTextureStride:R,numDirLights:o.directional.length,numPointLights:o.point.length,numSpotLights:o.spot.length,numSpotLightMaps:o.spotLightMap.length,numRectAreaLights:o.rectArea.length,numHemiLights:o.hemi.length,numDirLightShadows:o.directionalShadowMap.length,numPointLightShadows:o.pointShadowMap.length,numSpotLightShadows:o.spotShadowMap.length,numSpotLightShadowsWithMaps:o.numSpotLightShadowsWithMaps,numClippingPlanes:a.numPlanes,numClipIntersection:a.numIntersection,dithering:s.dithering,shadowMapEnabled:t.shadowMap.enabled&&h.length>0,shadowMapType:t.shadowMap.type,toneMapping:s.toneMapped?t.toneMapping:0,physicallyCorrectLights:t.physicallyCorrectLights,premultipliedAlpha:s.premultipliedAlpha,doubleSided:2===s.side,flipSided:1===s.side,useDepthPacking:!!s.depthPacking,depthPacking:s.depthPacking||0,index0AttributeName:s.index0AttributeName,extensionDerivatives:s.extensions&&s.extensions.derivatives,extensionFragDepth:s.extensions&&s.extensions.fragDepth,extensionDrawBuffers:s.extensions&&s.extensions.drawBuffers,extensionShaderTextureLOD:s.extensions&&s.extensions.shaderTextureLOD,rendererExtensionFragDepth:u||n.has("EXT_frag_depth"),rendererExtensionDrawBuffers:u||n.has("WEBGL_draw_buffers"),rendererExtensionShaderTextureLod:u||n.has("EXT_shader_texture_lod"),customProgramCacheKey:s.customProgramCacheKey()}},getProgramCacheKey:function(e){const i=[];if(e.shaderID?i.push(e.shaderID):(i.push(e.customVertexShaderID),i.push(e.customFragmentShaderID)),void 0!==e.defines)for(const t in e.defines)i.push(t),i.push(e.defines[t]);return!1===e.isRawShaderMaterial&&(!function(t,e){t.push(e.precision),t.push(e.outputEncoding),t.push(e.envMapMode),t.push(e.envMapCubeUVHeight),t.push(e.combine),t.push(e.vertexUvs),t.push(e.fogExp2),t.push(e.sizeAttenuation),t.push(e.morphTargetsCount),t.push(e.morphAttributeCount),t.push(e.numDirLights),t.push(e.numPointLights),t.push(e.numSpotLights),t.push(e.numSpotLightMaps),t.push(e.numHemiLights),t.push(e.numRectAreaLights),t.push(e.numDirLightShadows),t.push(e.numPointLightShadows),t.push(e.numSpotLightShadows),t.push(e.numSpotLightShadowsWithMaps),t.push(e.shadowMapType),t.push(e.toneMapping),t.push(e.numClippingPlanes),t.push(e.numClipIntersection),t.push(e.depthPacking)}(i,e),function(t,e){o.disableAll(),e.isWebGL2&&o.enable(0);e.supportsVertexTextures&&o.enable(1);e.instancing&&o.enable(2);e.instancingColor&&o.enable(3);e.map&&o.enable(4);e.matcap&&o.enable(5);e.envMap&&o.enable(6);e.lightMap&&o.enable(7);e.aoMap&&o.enable(8);e.emissiveMap&&o.enable(9);e.bumpMap&&o.enable(10);e.normalMap&&o.enable(11);e.objectSpaceNormalMap&&o.enable(12);e.tangentSpaceNormalMap&&o.enable(13);e.clearcoat&&o.enable(14);e.clearcoatMap&&o.enable(15);e.clearcoatRoughnessMap&&o.enable(16);e.clearcoatNormalMap&&o.enable(17);e.iridescence&&o.enable(18);e.iridescenceMap&&o.enable(19);e.iridescenceThicknessMap&&o.enable(20);e.displacementMap&&o.enable(21);e.specularMap&&o.enable(22);e.roughnessMap&&o.enable(23);e.metalnessMap&&o.enable(24);e.gradientMap&&o.enable(25);e.alphaMap&&o.enable(26);e.alphaTest&&o.enable(27);e.vertexColors&&o.enable(28);e.vertexAlphas&&o.enable(29);e.vertexUvs&&o.enable(30);e.vertexTangents&&o.enable(31);e.uvsVertexOnly&&o.enable(32);t.push(o.mask),o.disableAll(),e.fog&&o.enable(0);e.useFog&&o.enable(1);e.flatShading&&o.enable(2);e.logarithmicDepthBuffer&&o.enable(3);e.skinning&&o.enable(4);e.morphTargets&&o.enable(5);e.morphNormals&&o.enable(6);e.morphColors&&o.enable(7);e.premultipliedAlpha&&o.enable(8);e.shadowMapEnabled&&o.enable(9);e.physicallyCorrectLights&&o.enable(10);e.doubleSided&&o.enable(11);e.flipSided&&o.enable(12);e.useDepthPacking&&o.enable(13);e.dithering&&o.enable(14);e.specularIntensityMap&&o.enable(15);e.specularColorMap&&o.enable(16);e.transmission&&o.enable(17);e.transmissionMap&&o.enable(18);e.thicknessMap&&o.enable(19);e.sheen&&o.enable(20);e.sheenColorMap&&o.enable(21);e.sheenRoughnessMap&&o.enable(22);e.decodeVideoTexture&&o.enable(23);e.opaque&&o.enable(24);e.numMultiviewViews&&o.enable(25);t.push(o.mask)}(i,e),i.push(t.outputEncoding)),i.push(e.customProgramCacheKey),i.join()},getUniforms:function(t){const e=f[t.type];let i;if(e){const t=Sn[e];i=rn.clone(t.uniforms)}else i=t.uniforms;return i},acquireProgram:function(e,i){let n;for(let t=0,e=h.length;t0?n.push(h):!0===a.transparent?r.push(h):i.push(h)},unshift:function(t,e,a,o,l,c){const h=s(t,e,a,o,l,c);a.transmission>0?n.unshift(h):!0===a.transparent?r.unshift(h):i.unshift(h)},finish:function(){for(let i=e,n=t.length;i1&&i.sort(t||Es),n.length>1&&n.sort(e||Cs),r.length>1&&r.sort(e||Cs)}}}function Rs(){let t=new WeakMap;return{get:function(e,i){const n=t.get(e);let r;return void 0===n?(r=new Ls,t.set(e,[r])):i>=n.length?(r=new Ls,n.push(r)):r=n[i],r},dispose:function(){t=new WeakMap}}}function Ps(){const t={};return{get:function(e){if(void 0!==t[e.id])return t[e.id];let i;switch(e.type){case"DirectionalLight":i={direction:new re,color:new qt};break;case"SpotLight":i={position:new re,direction:new re,color:new qt,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case"PointLight":i={position:new re,color:new qt,distance:0,decay:0};break;case"HemisphereLight":i={direction:new re,skyColor:new qt,groundColor:new qt};break;case"RectAreaLight":i={color:new qt,position:new re,halfWidth:new re,halfHeight:new re}}return t[e.id]=i,i}}}let Is=0;function Ds(t,e){return(e.castShadow?2:0)-(t.castShadow?2:0)+(e.map?1:0)-(t.map?1:0)}function Ns(t,e){const i=new Ps,n=function(){const t={};return{get:function(e){if(void 0!==t[e.id])return t[e.id];let i;switch(e.type){case"DirectionalLight":case"SpotLight":i={shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new Lt};break;case"PointLight":i={shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new Lt,shadowCameraNear:1,shadowCameraFar:1e3}}return t[e.id]=i,i}}}(),r={version:0,hash:{directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,numDirectionalShadows:-1,numPointShadows:-1,numSpotShadows:-1,numSpotMaps:-1},ambient:[0,0,0],probe:[],directional:[],directionalShadow:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotLightMap:[],spotShadow:[],spotShadowMap:[],spotLightMatrix:[],rectArea:[],rectAreaLTC1:null,rectAreaLTC2:null,point:[],pointShadow:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[],numSpotLightShadowsWithMaps:0};for(let t=0;t<9;t++)r.probe.push(new re);const s=new re,a=new Ne,o=new Ne;return{setup:function(s,a){let o=0,l=0,c=0;for(let t=0;t<9;t++)r.probe[t].set(0,0,0);let h=0,u=0,d=0,p=0,m=0,f=0,g=0,v=0,x=0,_=0;s.sort(Ds);const y=!0!==a?Math.PI:1;for(let t=0,e=s.length;t0&&(e.isWebGL2||!0===t.has("OES_texture_float_linear")?(r.rectAreaLTC1=wn.LTC_FLOAT_1,r.rectAreaLTC2=wn.LTC_FLOAT_2):!0===t.has("OES_texture_half_float_linear")?(r.rectAreaLTC1=wn.LTC_HALF_1,r.rectAreaLTC2=wn.LTC_HALF_2):console.error("THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions.")),r.ambient[0]=o,r.ambient[1]=l,r.ambient[2]=c;const M=r.hash;M.directionalLength===h&&M.pointLength===u&&M.spotLength===d&&M.rectAreaLength===p&&M.hemiLength===m&&M.numDirectionalShadows===f&&M.numPointShadows===g&&M.numSpotShadows===v&&M.numSpotMaps===x||(r.directional.length=h,r.spot.length=d,r.rectArea.length=p,r.point.length=u,r.hemi.length=m,r.directionalShadow.length=f,r.directionalShadowMap.length=f,r.pointShadow.length=g,r.pointShadowMap.length=g,r.spotShadow.length=v,r.spotShadowMap.length=v,r.directionalShadowMatrix.length=f,r.pointShadowMatrix.length=g,r.spotLightMatrix.length=v+x-_,r.spotLightMap.length=x,r.numSpotLightShadowsWithMaps=_,M.directionalLength=h,M.pointLength=u,M.spotLength=d,M.rectAreaLength=p,M.hemiLength=m,M.numDirectionalShadows=f,M.numPointShadows=g,M.numSpotShadows=v,M.numSpotMaps=x,r.version=Is++)},setupView:function(t,e){let i=0,n=0,l=0,c=0,h=0;const u=e.matrixWorldInverse;for(let e=0,d=t.length;e=s.length?(a=new Os(t,e),s.push(a)):a=s[r],a},dispose:function(){i=new WeakMap}}}class Us extends xi{constructor(t){super(),this.isMeshDepthMaterial=!0,this.type="MeshDepthMaterial",this.depthPacking=3200,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.setValues(t)}copy(t){return super.copy(t),this.depthPacking=t.depthPacking,this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this}}class Bs extends xi{constructor(t){super(),this.isMeshDistanceMaterial=!0,this.type="MeshDistanceMaterial",this.referencePosition=new re,this.nearDistance=1,this.farDistance=1e3,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.setValues(t)}copy(t){return super.copy(t),this.referencePosition.copy(t.referencePosition),this.nearDistance=t.nearDistance,this.farDistance=t.farDistance,this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this}}function Fs(t,e,i){let n=new xn;const r=new Lt,s=new Lt,a=new Qt,o=new Us({depthPacking:3201}),l=new Bs,c={},h=i.maxTextureSize,u={0:1,1:0,2:2},p=new sn({defines:{VSM_SAMPLES:8},uniforms:{shadow_pass:{value:null},resolution:{value:new Lt},radius:{value:4}},vertexShader:"void main() {\n\tgl_Position = vec4( position, 1.0 );\n}",fragmentShader:"uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include \nvoid main() {\n\tconst float samples = float( VSM_SAMPLES );\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n\tfloat uvStart = samples <= 1.0 ? 0.0 : - 1.0;\n\tfor ( float i = 0.0; i < samples; i ++ ) {\n\t\tfloat uvOffset = uvStart + i * uvStride;\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean / samples;\n\tsquared_mean = squared_mean / samples;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}"}),m=p.clone();m.defines.HORIZONTAL_PASS=1;const f=new Di;f.setAttribute("position",new bi(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));const g=new Ki(f,p),v=this;function x(i,n){const s=e.update(g);p.defines.VSM_SAMPLES!==i.blurSamples&&(p.defines.VSM_SAMPLES=i.blurSamples,m.defines.VSM_SAMPLES=i.blurSamples,p.needsUpdate=!0,m.needsUpdate=!0),null===i.mapPass&&(i.mapPass=new te(r.x,r.y)),p.uniforms.shadow_pass.value=i.map.texture,p.uniforms.resolution.value=i.mapSize,p.uniforms.radius.value=i.radius,t.setRenderTarget(i.mapPass),t.clear(),t.renderBufferDirect(n,null,s,p,g,null),m.uniforms.shadow_pass.value=i.mapPass.texture,m.uniforms.resolution.value=i.mapSize,m.uniforms.radius.value=i.radius,t.setRenderTarget(i.map),t.clear(),t.renderBufferDirect(n,null,s,m,g,null)}function _(e,i,n,r,s,a){let h=null;const d=!0===n.isPointLight?e.customDistanceMaterial:e.customDepthMaterial;if(h=void 0!==d?d:!0===n.isPointLight?l:o,t.localClippingEnabled&&!0===i.clipShadows&&Array.isArray(i.clippingPlanes)&&0!==i.clippingPlanes.length||i.displacementMap&&0!==i.displacementScale||i.alphaMap&&i.alphaTest>0||i.map&&i.alphaTest>0){const t=h.uuid,e=i.uuid;let n=c[t];void 0===n&&(n={},c[t]=n);let r=n[e];void 0===r&&(r=h.clone(),n[e]=r),h=r}return h.visible=i.visible,h.wireframe=i.wireframe,h.side=3===a?null!==i.shadowSide?i.shadowSide:i.side:null!==i.shadowSide?i.shadowSide:u[i.side],h.alphaMap=i.alphaMap,h.alphaTest=i.alphaTest,h.map=i.map,h.clipShadows=i.clipShadows,h.clippingPlanes=i.clippingPlanes,h.clipIntersection=i.clipIntersection,h.displacementMap=i.displacementMap,h.displacementScale=i.displacementScale,h.displacementBias=i.displacementBias,h.wireframeLinewidth=i.wireframeLinewidth,h.linewidth=i.linewidth,!0===n.isPointLight&&!0===h.isMeshDistanceMaterial&&(h.referencePosition.setFromMatrixPosition(n.matrixWorld),h.nearDistance=r,h.farDistance=s),h}function y(i,r,s,a,o){if(!1===i.visible)return;if(i.layers.test(r.layers)&&(i.isMesh||i.isLine||i.isPoints)&&(i.castShadow||i.receiveShadow&&3===o)&&(!i.frustumCulled||n.intersectsObject(i))){i.modelViewMatrix.multiplyMatrices(s.matrixWorldInverse,i.matrixWorld);const n=e.update(i),r=i.material;if(Array.isArray(r)){const e=n.groups;for(let l=0,c=e.length;lh||r.y>h)&&(r.x>h&&(s.x=Math.floor(h/m.x),r.x=s.x*m.x,u.mapSize.x=s.x),r.y>h&&(s.y=Math.floor(h/m.y),r.y=s.y*m.y,u.mapSize.y=s.y)),null===u.map){const t=3!==this.type?{minFilter:d,magFilter:d}:{};u.map=new te(r.x,r.y,t),u.map.texture.name=c.name+".shadowMap",u.camera.updateProjectionMatrix()}t.setRenderTarget(u.map),t.clear();const f=u.getViewportCount();for(let t=0;t=1):-1!==I.indexOf("OpenGL ES")&&(P=parseFloat(/^OpenGL ES (\d)/.exec(I)[1]),R=P>=2);let D=null,N={};const O=t.getParameter(3088),z=t.getParameter(2978),U=(new Qt).fromArray(O),B=(new Qt).fromArray(z);function F(e,i,n){const r=new Uint8Array(4),s=t.createTexture();t.bindTexture(e,s),t.texParameteri(e,10241,9728),t.texParameteri(e,10240,9728);for(let e=0;en||t.height>n)&&(r=n/Math.max(t.width,t.height)),r<1||!0===e){if("undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap){const n=e?Tt:Math.floor,s=n(r*t.width),a=n(r*t.height);void 0===N&&(N=B(s,a));const o=i?B(s,a):N;o.width=s,o.height=a;return o.getContext("2d").drawImage(t,0,0,s,a),console.warn("THREE.WebGLRenderer: Texture has been resized from ("+t.width+"x"+t.height+") to ("+s+"x"+a+")."),o}return"data"in t&&console.warn("THREE.WebGLRenderer: Image in DataTexture is too big ("+t.width+"x"+t.height+")."),t}return t}function k(t){return wt(t.width)&&wt(t.height)}function G(t,e){return t.generateMipmaps&&e&&t.minFilter!==d&&t.minFilter!==f}function V(e){t.generateMipmap(e)}function H(i,n,r,s,a=!1){if(!1===o)return n;if(null!==i){if(void 0!==t[i])return t[i];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+i+"'")}let l=n;return 6403===n&&(5126===r&&(l=33326),5131===r&&(l=33325),5121===r&&(l=33321)),33319===n&&(5126===r&&(l=33328),5131===r&&(l=33327),5121===r&&(l=33323)),6408===n&&(5126===r&&(l=34836),5131===r&&(l=34842),5121===r&&(l=s===ot&&!1===a?35907:32856),32819===r&&(l=32854),32820===r&&(l=32855)),33325!==l&&33326!==l&&33327!==l&&33328!==l&&34842!==l&&34836!==l||e.get("EXT_color_buffer_float"),l}function W(t,e,i){return!0===G(t,i)||t.isFramebufferTexture&&t.minFilter!==d&&t.minFilter!==f?Math.log2(Math.max(e.width,e.height))+1:void 0!==t.mipmaps&&t.mipmaps.length>0?t.mipmaps.length:t.isCompressedTexture&&Array.isArray(t.image)?e.mipmaps.length:1}function j(t){return t===d||t===p||t===m?9728:9729}function q(t){const e=t.target;e.removeEventListener("dispose",q),function(t){const e=n.get(t);if(void 0===e.__webglInit)return;const i=t.source,r=O.get(i);if(r){const n=r[e.__cacheKey];n.usedTimes--,0===n.usedTimes&&Y(t),0===Object.keys(r).length&&O.delete(i)}n.remove(t)}(e),e.isVideoTexture&&D.delete(e)}function X(e){const i=e.target;i.removeEventListener("dispose",X),function(e){const i=e.texture,r=n.get(e),s=n.get(i);void 0!==s.__webglTexture&&(t.deleteTexture(s.__webglTexture),a.memory.textures--);e.depthTexture&&e.depthTexture.dispose();if(e.isWebGLCubeRenderTarget)for(let e=0;e<6;e++)t.deleteFramebuffer(r.__webglFramebuffer[e]),r.__webglDepthbuffer&&t.deleteRenderbuffer(r.__webglDepthbuffer[e]);else{if(t.deleteFramebuffer(r.__webglFramebuffer),r.__webglDepthbuffer&&t.deleteRenderbuffer(r.__webglDepthbuffer),r.__webglMultisampledFramebuffer&&t.deleteFramebuffer(r.__webglMultisampledFramebuffer),r.__webglColorRenderbuffer)for(let e=0;e1||n.get(s).__currentAnisotropy)&&(t.texParameterf(i,a.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(s.anisotropy,r.getMaxAnisotropy())),n.get(s).__currentAnisotropy=s.anisotropy)}}function Q(e,i){let n=!1;void 0===e.__webglInit&&(e.__webglInit=!0,i.addEventListener("dispose",q));const r=i.source;let s=O.get(r);void 0===s&&(s={},O.set(r,s));const o=function(t){const e=[];return e.push(t.wrapS),e.push(t.wrapT),e.push(t.wrapR||0),e.push(t.magFilter),e.push(t.minFilter),e.push(t.anisotropy),e.push(t.internalFormat),e.push(t.format),e.push(t.type),e.push(t.generateMipmaps),e.push(t.premultiplyAlpha),e.push(t.flipY),e.push(t.unpackAlignment),e.push(t.encoding),e.join()}(i);if(o!==e.__cacheKey){void 0===s[o]&&(s[o]={texture:t.createTexture(),usedTimes:0},a.memory.textures++,n=!0),s[o].usedTimes++;const r=s[e.__cacheKey];void 0!==r&&(s[e.__cacheKey].usedTimes--,0===r.usedTimes&&Y(i)),e.__cacheKey=o,e.__webglTexture=s[o].texture}return n}function tt(e,r,a,o,l){const c=s.convert(a.format,a.encoding),h=s.convert(a.type),u=H(a.internalFormat,c,h,a.encoding);n.get(r).__hasExternalTextures||(!0===r.isWebGLMultiviewRenderTarget?i.texStorage3D(35866,0,u,r.width,r.height,r.numViews):32879===l||35866===l?i.texImage3D(l,0,u,r.width,r.height,r.depth,0,c,h,null):i.texImage2D(l,0,u,r.width,r.height,0,c,h,null)),i.bindFramebuffer(36160,e);const d=nt(r);!0===r.isWebGLMultiviewRenderTarget?d?I.framebufferTextureMultisampleMultiviewOVR(36160,36064,n.get(a).__webglTexture,0,it(r),0,r.numViews):I.framebufferTextureMultiviewOVR(36160,36064,n.get(a).__webglTexture,0,0,r.numViews):(3553===l||l>=34069&&l<=34074)&&(d?R.framebufferTexture2DMultisampleEXT(36160,o,l,n.get(a).__webglTexture,0,it(r)):t.framebufferTexture2D(36160,o,l,n.get(a).__webglTexture,0)),i.bindFramebuffer(36160,null)}function et(e,i,r){if(t.bindRenderbuffer(36161,e),!0===i.isWebGLMultiviewRenderTarget){const e=nt(i),r=i.numViews,s=i.depthTexture;let a=33190,o=36096;s&&s.isDepthTexture&&(s.type===M?a=36012:s.type===w&&(a=35056,o=33306));let l=n.get(i.depthTexture).__webglTexture;void 0===l&&(l=t.createTexture(),t.bindTexture(35866,l),t.texStorage3D(35866,1,a,i.width,i.height,r)),e?I.framebufferTextureMultisampleMultiviewOVR(36160,o,l,0,it(i),0,r):I.framebufferTextureMultiviewOVR(36160,o,l,0,0,r)}else if(i.depthBuffer&&!i.stencilBuffer){let n=33189;if(r||nt(i)){const e=i.depthTexture;e&&e.isDepthTexture&&(e.type===M?n=36012:e.type===y&&(n=33190));const r=it(i);nt(i)?R.renderbufferStorageMultisampleEXT(36161,r,n,i.width,i.height):t.renderbufferStorageMultisample(36161,r,n,i.width,i.height)}else t.renderbufferStorage(36161,n,i.width,i.height);t.framebufferRenderbuffer(36160,36096,36161,e)}else if(i.depthBuffer&&i.stencilBuffer){const n=it(i);r&&!1===nt(i)?t.renderbufferStorageMultisample(36161,n,35056,i.width,i.height):nt(i)?R.renderbufferStorageMultisampleEXT(36161,n,35056,i.width,i.height):t.renderbufferStorage(36161,34041,i.width,i.height),t.framebufferRenderbuffer(36160,33306,36161,e)}else{const e=!0===i.isWebGLMultipleRenderTargets?i.texture:[i.texture];for(let n=0;n0&&!0===e.has("WEBGL_multisampled_render_to_texture")&&!1!==i.__useRenderToTexture}function rt(t,i){const n=t.encoding,r=t.format,s=t.type;return!0===t.isCompressedTexture||!0===t.isVideoTexture||t.format===pt||n!==at&&(n===ot?!1===o?!0===e.has("EXT_sRGB")&&r===S?(t.format=pt,t.minFilter=f,t.generateMipmaps=!1):i=Yt.sRGBToLinear(i):r===S&&s===x||console.warn("THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType."):console.error("THREE.WebGLTextures: Unsupported texture encoding:",n)),i}this.allocateTextureUnit=function(){const t=Z;return t>=l&&console.warn("THREE.WebGLTextures: Trying to use "+t+" texture units while this GPU supports only "+l),Z+=1,t},this.resetTextureUnits=function(){Z=0},this.setTexture2D=function(t,e){const r=n.get(t);if(t.isVideoTexture&&function(t){const e=a.render.frame;D.get(t)!==e&&(D.set(t,e),t.update())}(t),!1===t.isRenderTargetTexture&&t.version>0&&r.__version!==t.version){const i=t.image;if(null===i)console.warn("THREE.WebGLRenderer: Texture marked for update but no image data found.");else if(!1===i.complete)console.warn("THREE.WebGLRenderer: Texture marked for update but image is incomplete");else if(this.uploadTexture(r,t,e))return}i.bindTexture(3553,r.__webglTexture,33984+e)},this.setTexture2DArray=function(t,e){const r=n.get(t);t.version>0&&r.__version!==t.version?this.uploadTexture(r,t,e):i.bindTexture(35866,r.__webglTexture,33984+e)},this.setTexture3D=function(t,e){const r=n.get(t);t.version>0&&r.__version!==t.version?this.uploadTexture(r,t,e):i.bindTexture(32879,r.__webglTexture,33984+e)},this.setTextureCube=function(e,r){const a=n.get(e);e.version>0&&a.__version!==e.version?function(e,r,a){if(6!==r.image.length)return;const l=Q(e,r),c=r.source;i.bindTexture(34067,e.__webglTexture,33984+a);const h=n.get(c);if(c.version!==h.__version||!0===l){i.activeTexture(33984+a),t.pixelStorei(37440,r.flipY),t.pixelStorei(37441,r.premultiplyAlpha),t.pixelStorei(3317,r.unpackAlignment),t.pixelStorei(37443,0);const e=r.isCompressedTexture||r.image[0].isCompressedTexture,n=r.image[0]&&r.image[0].isDataTexture,u=[];for(let t=0;t<6;t++)u[t]=e||n?n?r.image[t].image:r.image[t]:F(r.image[t],!1,!0,E),u[t]=rt(r,u[t]);const d=u[0],p=k(d)||o,m=s.convert(r.format,r.encoding),f=s.convert(r.type),g=H(r.internalFormat,m,f,r.encoding),v=o&&!0!==r.isVideoTexture,x=void 0===h.__version||!0===l;let _,y=W(r,d,p);if($(34067,r,p),e){v&&x&&i.texStorage2D(34067,y,g,d.width,d.height);for(let t=0;t<6;t++){_=u[t].mipmaps;for(let e=0;e<_.length;e++){const n=_[e];r.format!==S?null!==m?v?i.compressedTexSubImage2D(34069+t,e,0,0,n.width,n.height,m,n.data):i.compressedTexImage2D(34069+t,e,g,n.width,n.height,0,n.data):console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()"):v?i.texSubImage2D(34069+t,e,0,0,n.width,n.height,m,f,n.data):i.texImage2D(34069+t,e,g,n.width,n.height,0,m,f,n.data)}}}else{_=r.mipmaps,v&&x&&(_.length>0&&y++,i.texStorage2D(34067,y,g,u[0].width,u[0].height));for(let t=0;t<6;t++)if(n){v?i.texSubImage2D(34069+t,0,0,0,u[t].width,u[t].height,m,f,u[t].data):i.texImage2D(34069+t,0,g,u[t].width,u[t].height,0,m,f,u[t].data);for(let e=0;e<_.length;e++){const n=_[e].image[t].image;v?i.texSubImage2D(34069+t,e+1,0,0,n.width,n.height,m,f,n.data):i.texImage2D(34069+t,e+1,g,n.width,n.height,0,m,f,n.data)}}else{v?i.texSubImage2D(34069+t,0,0,0,m,f,u[t]):i.texImage2D(34069+t,0,g,m,f,u[t]);for(let e=0;e<_.length;e++){const n=_[e];v?i.texSubImage2D(34069+t,e+1,0,0,m,f,n.image[t]):i.texImage2D(34069+t,e+1,g,m,f,n.image[t])}}}G(r,p)&&V(34067),h.__version=c.version,r.onUpdate&&r.onUpdate(r)}e.__version=r.version}(a,e,r):i.bindTexture(34067,a.__webglTexture,33984+r)},this.rebindTextures=function(t,e,i){const r=n.get(t);void 0!==e&&this.setupFrameBufferTexture(r.__webglFramebuffer,t,t.texture,36064,3553),void 0!==i&&this.setupDepthRenderbuffer(t)},this.uploadTexture=function(e,r,a){if(this.deferTextureUploads)return r.isPendingDeferredUpload||(r.isPendingDeferredUpload=!0,z.push({textureProperties:e,texture:r,slot:a})),!1;let l=3553;(r.isDataArrayTexture||r.isCompressedArrayTexture)&&(l=35866),r.isData3DTexture&&(l=32879);const c=Q(e,r),u=r.source;i.bindTexture(l,e.__webglTexture,33984+a);const p=n.get(u);if(u.version!==p.__version||!0===c){i.activeTexture(33984+a),t.pixelStorei(37440,r.flipY),t.pixelStorei(37441,r.premultiplyAlpha),t.pixelStorei(3317,r.unpackAlignment),t.pixelStorei(37443,0);const e=function(t){return!o&&(t.wrapS!==h||t.wrapT!==h||t.minFilter!==d&&t.minFilter!==f)}(r)&&!1===k(r.image);let n=F(r.image,e,!1,C);n=rt(r,n);const m=k(n)||o,g=s.convert(r.format,r.encoding);let v,x=s.convert(r.type),b=H(r.internalFormat,g,x,r.encoding,r.isVideoTexture);$(l,r,m);const E=r.mipmaps,L=o&&!0!==r.isVideoTexture,R=void 0===p.__version||!0===c,P=W(r,n,m);if(r.isDepthTexture)b=6402,o?b=r.type===M?36012:r.type===y?33190:r.type===w?35056:33189:r.type===M&&console.error("WebGLRenderer: Floating point depth texture requires WebGL2."),r.format===T&&6402===b&&r.type!==_&&r.type!==y&&(console.warn("THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture."),r.type=y,x=s.convert(r.type)),r.format===A&&6402===b&&(b=34041,r.type!==w&&(console.warn("THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture."),r.type=w,x=s.convert(r.type))),R&&(L?i.texStorage2D(3553,1,b,n.width,n.height):i.texImage2D(3553,0,b,n.width,n.height,0,g,x,null));else if(r.isDataTexture)if(E.length>0&&m){L&&R&&i.texStorage2D(3553,P,b,E[0].width,E[0].height);for(let t=0,e=E.length;t>=1,e>>=1}}else if(E.length>0&&m){L&&R&&i.texStorage2D(3553,P,b,E[0].width,E[0].height);for(let t=0,e=E.length;t0&&!1===nt(e)){const n=d?l:[l];c.__webglMultisampledFramebuffer=t.createFramebuffer(),c.__webglColorRenderbuffer=[],i.bindFramebuffer(36160,c.__webglMultisampledFramebuffer);for(let i=0;i0&&!1===nt(e)){const r=e.isWebGLMultipleRenderTargets?e.texture:[e.texture],s=e.width,a=e.height;let o=16384;const l=[],c=e.stencilBuffer?33306:36096,h=n.get(e),u=!0===e.isWebGLMultipleRenderTargets;if(u)for(let e=0;eo+c?(l.inputState.pinching=!1,this.dispatchEvent({type:"pinchend",handedness:t.handedness,target:this})):!l.inputState.pinching&&a<=o-c&&(l.inputState.pinching=!0,this.dispatchEvent({type:"pinchstart",handedness:t.handedness,target:this}))}else null!==o&&t.gripSpace&&(r=e.getPose(t.gripSpace,i),null!==r&&(o.matrix.fromArray(r.transform.matrix),o.matrix.decompose(o.position,o.rotation,o.scale),r.linearVelocity?(o.hasLinearVelocity=!0,o.linearVelocity.copy(r.linearVelocity)):o.hasLinearVelocity=!1,r.angularVelocity?(o.hasAngularVelocity=!0,o.angularVelocity.copy(r.angularVelocity)):o.hasAngularVelocity=!1));null!==a&&(n=e.getPose(t.targetRaySpace,i),null===n&&null!==r&&(n=r),null!==n&&(a.matrix.fromArray(n.transform.matrix),a.matrix.decompose(a.position,a.rotation,a.scale),n.linearVelocity?(a.hasLinearVelocity=!0,a.linearVelocity.copy(n.linearVelocity)):a.hasLinearVelocity=!1,n.angularVelocity?(a.hasAngularVelocity=!0,a.angularVelocity.copy(n.angularVelocity)):a.hasAngularVelocity=!1,this.dispatchEvent(Js)))}return null!==a&&(a.visible=null!==n),null!==o&&(o.visible=null!==r),null!==l&&(l.visible=null!==s),this}_getHandJoint(t,e){if(void 0===t.joints[e.jointName]){const i=new Ws;i.matrixAutoUpdate=!1,i.visible=!1,t.joints[e.jointName]=i,t.add(i)}return t.joints[e.jointName]}}class $s extends $t{constructor(t,e,i,n,r,s,a,o,l,c){if((c=void 0!==c?c:T)!==T&&c!==A)throw new Error("DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat");void 0===i&&c===T&&(i=y),void 0===i&&c===A&&(i=w),super(null,n,r,s,a,o,c,i,l),this.isDepthTexture=!0,this.image={width:t,height:e},this.magFilter=void 0!==a?a:d,this.minFilter=void 0!==o?o:d,this.flipY=!1,this.generateMipmaps=!1}}class Qs extends mt{constructor(t,e,i,n){super();const r=this;let s=null,a=1;var o=null;let l=null,c="local-floor",h=null,u=null;var d=[];let p=null,m=null,f=null,g=null;const v=e.getContextAttributes();let _=null,M=null;const b=[],E=[],C=new Set,L=new Map,R=new on;R.layers.enable(1),R.viewport=new Qt;const P=new on;P.layers.enable(2),P.viewport=new Qt;const I=[R,P],D=new js;D.layers.enable(1),D.layers.enable(2);let N=null,O=null;function z(t){const e=E.indexOf(t.inputSource);if(-1===e)return;const i=b[e];void 0!==i&&i.dispatchEvent({type:t.type,data:t.inputSource})}function U(){s.removeEventListener("select",z),s.removeEventListener("selectstart",z),s.removeEventListener("selectend",z),s.removeEventListener("squeeze",z),s.removeEventListener("squeezestart",z),s.removeEventListener("squeezeend",z),s.removeEventListener("end",U),s.removeEventListener("inputsourceschange",B);for(let t=0;t=0&&(E[n]=null,b[n].disconnect(i))}for(let e=0;e=E.length){E.push(i),n=t;break}if(null===E[t]){E[t]=i,n=t;break}}if(-1===n)break}const r=b[n];r&&r.connect(i)}}this.cameraAutoUpdate=!0,this.layersEnabled=!1,this.enabled=!1,this.isPresenting=!1,this.isMultiview=!1,this.getCameraPose=function(){return u},this.getController=function(t){let e=b[t];return void 0===e&&(e=new Ks,b[t]=e),e.getTargetRaySpace()},this.getControllerGrip=function(t){let e=b[t];return void 0===e&&(e=new Ks,b[t]=e),e.getGripSpace()},this.getHand=function(t){let e=b[t];return void 0===e&&(e=new Ks,b[t]=e),e.getHandSpace()},this.setFramebufferScaleFactor=function(t){a=t,!0===r.isPresenting&&console.warn("THREE.WebXRManager: Cannot change framebuffer scale while presenting.")},this.setReferenceSpaceType=function(t){c=t,!0===r.isPresenting&&console.warn("THREE.WebXRManager: Cannot change reference space type while presenting.")},this.getReferenceSpace=function(){return h||l},this.setReferenceSpace=function(t){h=t},this.getBaseLayer=function(){return null!==m?m:f},this.getBinding=function(){return p},this.getFrame=function(){return g},this.getSession=function(){return s},this.setSession=async function(o){if(s=o,null!==s){if(_=t.getRenderTarget(),s.addEventListener("select",z),s.addEventListener("selectstart",z),s.addEventListener("selectend",z),s.addEventListener("squeeze",z),s.addEventListener("squeezestart",z),s.addEventListener("squeezeend",z),s.addEventListener("end",U),s.addEventListener("inputsourceschange",B),!0!==v.xrCompatible&&await e.makeXRCompatible(),void 0===s.renderState.layers||!1===t.capabilities.isWebGL2){const i={antialias:void 0!==s.renderState.layers||v.antialias,alpha:v.alpha,depth:v.depth,stencil:v.stencil,framebufferScaleFactor:a};f=new XRWebGLLayer(s,e,i),s.updateRenderState({baseLayer:f}),M=new te(f.framebufferWidth,f.framebufferHeight,{format:S,type:x,encoding:t.outputEncoding,stencilBuffer:v.stencil})}else{let o=null,l=null,c=null;v.depth&&(c=v.stencil?35056:33190,o=v.stencil?A:T,l=v.stencil?w:y),r.isMultiview=n&&i.has("OCULUS_multiview");const h={colorFormat:32856,depthFormat:c,scaleFactor:a};r.isMultiview&&(h.textureType="texture-array"),p=new XRWebGLBinding(s,e),m=p.createProjectionLayer(h),s.updateRenderState({layers:[m]});const u={format:S,type:x,depthTexture:new $s(m.textureWidth,m.textureHeight,l,void 0,void 0,void 0,void 0,void 0,void 0,o),stencilBuffer:v.stencil,encoding:t.outputEncoding,samples:v.antialias?4:0};if(r.isMultiview){const t=i.get("OCULUS_multiview");this.maxNumViews=e.getParameter(t.MAX_VIEWS_OVR),M=new Zs(m.textureWidth,m.textureHeight,2,u)}else M=new te(m.textureWidth,m.textureHeight,u);t.properties.get(M).__ignoreDepthValues=m.ignoreDepthValues}M.isXRRenderTarget=!0,this.setFoveation(1),h=null,l=await s.requestReferenceSpace(c),H.setContext(s),H.start(),r.isPresenting=!0,r.dispatchEvent({type:"sessionstart"})}},this.addLayer=function(t){window.XRWebGLBinding&&this.layersEnabled&&s&&(d.push(t),this.updateLayers())},this.removeLayer=function(t){d.splice(d.indexOf(t),1),window.XRWebGLBinding&&this.layersEnabled&&s&&this.updateLayers()},this.updateLayers=function(){var t=d.map((function(t){return t}));t.unshift(s.renderState.layers[0]),s.updateRenderState({layers:t})};const F=new re,k=new re;function G(t,e){null===e?t.matrixWorld.copy(t.matrix):t.matrixWorld.multiplyMatrices(e.matrixWorld,t.matrix),t.matrixWorldInverse.copy(t.matrixWorld).invert()}this.setPoseTarget=function(t){void 0!==t&&(o=t)},this.updateCamera=function(t){if(null===s)return;D.near=P.near=R.near=t.near,D.far=P.far=R.far=t.far,N===D.near&&O===D.far||(s.updateRenderState({depthNear:D.near,depthFar:D.far}),N=D.near,O=D.far);const e=D.cameras;var i=o||t;const n=i.parent;G(D,n);for(let t=0;te&&(L.set(t,t.lastChangedTime),r.dispatchEvent({type:"planechanged",data:t}))}else C.add(t),L.set(t,i.lastChangedTime),r.dispatchEvent({type:"planeadded",data:t})}g=null})),this.setAnimationLoop=function(t){V=t},this.dispose=function(){}}}function ta(t,e){function i(i,n){i.opacity.value=n.opacity,n.color&&i.diffuse.value.copy(n.color),n.emissive&&i.emissive.value.copy(n.emissive).multiplyScalar(n.emissiveIntensity),n.map&&(i.map.value=n.map),n.alphaMap&&(i.alphaMap.value=n.alphaMap),n.bumpMap&&(i.bumpMap.value=n.bumpMap,i.bumpScale.value=n.bumpScale,1===n.side&&(i.bumpScale.value*=-1)),n.displacementMap&&(i.displacementMap.value=n.displacementMap,i.displacementScale.value=n.displacementScale,i.displacementBias.value=n.displacementBias),n.emissiveMap&&(i.emissiveMap.value=n.emissiveMap),n.normalMap&&(i.normalMap.value=n.normalMap,i.normalScale.value.copy(n.normalScale),1===n.side&&i.normalScale.value.negate()),n.specularMap&&(i.specularMap.value=n.specularMap),n.alphaTest>0&&(i.alphaTest.value=n.alphaTest);const r=e.get(n).envMap;if(r&&(i.envMap.value=r,i.flipEnvMap.value=r.isCubeTexture&&!1===r.isRenderTargetTexture?-1:1,i.reflectivity.value=n.reflectivity,i.ior.value=n.ior,i.refractionRatio.value=n.refractionRatio),n.lightMap){i.lightMap.value=n.lightMap;const e=!0!==t.physicallyCorrectLights?Math.PI:1;i.lightMapIntensity.value=n.lightMapIntensity*e}let s,a;n.aoMap&&(i.aoMap.value=n.aoMap,i.aoMapIntensity.value=n.aoMapIntensity),n.map?s=n.map:n.specularMap?s=n.specularMap:n.displacementMap?s=n.displacementMap:n.normalMap?s=n.normalMap:n.bumpMap?s=n.bumpMap:n.roughnessMap?s=n.roughnessMap:n.metalnessMap?s=n.metalnessMap:n.alphaMap?s=n.alphaMap:n.emissiveMap?s=n.emissiveMap:n.clearcoatMap?s=n.clearcoatMap:n.clearcoatNormalMap?s=n.clearcoatNormalMap:n.clearcoatRoughnessMap?s=n.clearcoatRoughnessMap:n.iridescenceMap?s=n.iridescenceMap:n.iridescenceThicknessMap?s=n.iridescenceThicknessMap:n.specularIntensityMap?s=n.specularIntensityMap:n.specularColorMap?s=n.specularColorMap:n.transmissionMap?s=n.transmissionMap:n.thicknessMap?s=n.thicknessMap:n.sheenColorMap?s=n.sheenColorMap:n.sheenRoughnessMap&&(s=n.sheenRoughnessMap),void 0!==s&&(s.isWebGLRenderTarget&&(s=s.texture),!0===s.matrixAutoUpdate&&s.updateMatrix(),i.uvTransform.value.copy(s.matrix)),n.aoMap?a=n.aoMap:n.lightMap&&(a=n.lightMap),void 0!==a&&(a.isWebGLRenderTarget&&(a=a.texture),!0===a.matrixAutoUpdate&&a.updateMatrix(),i.uv2Transform.value.copy(a.matrix))}return{refreshFogUniforms:function(e,i){i.color.getRGB(e.fogColor.value,nn(t)),i.isFog?(e.fogNear.value=i.near,e.fogFar.value=i.far):i.isFogExp2&&(e.fogDensity.value=i.density)},refreshMaterialUniforms:function(t,n,r,s,a){n.isMeshBasicMaterial||n.isMeshLambertMaterial?i(t,n):n.isMeshToonMaterial?(i(t,n),function(t,e){e.gradientMap&&(t.gradientMap.value=e.gradientMap)}(t,n)):n.isMeshPhongMaterial?(i(t,n),function(t,e){t.specular.value.copy(e.specular),t.shininess.value=Math.max(e.shininess,1e-4)}(t,n)):n.isMeshStandardMaterial?(i(t,n),function(t,i){t.roughness.value=i.roughness,t.metalness.value=i.metalness,i.roughnessMap&&(t.roughnessMap.value=i.roughnessMap);i.metalnessMap&&(t.metalnessMap.value=i.metalnessMap);e.get(i).envMap&&(t.envMapIntensity.value=i.envMapIntensity)}(t,n),n.isMeshPhysicalMaterial&&function(t,e,i){t.ior.value=e.ior,e.sheen>0&&(t.sheenColor.value.copy(e.sheenColor).multiplyScalar(e.sheen),t.sheenRoughness.value=e.sheenRoughness,e.sheenColorMap&&(t.sheenColorMap.value=e.sheenColorMap),e.sheenRoughnessMap&&(t.sheenRoughnessMap.value=e.sheenRoughnessMap));e.clearcoat>0&&(t.clearcoat.value=e.clearcoat,t.clearcoatRoughness.value=e.clearcoatRoughness,e.clearcoatMap&&(t.clearcoatMap.value=e.clearcoatMap),e.clearcoatRoughnessMap&&(t.clearcoatRoughnessMap.value=e.clearcoatRoughnessMap),e.clearcoatNormalMap&&(t.clearcoatNormalScale.value.copy(e.clearcoatNormalScale),t.clearcoatNormalMap.value=e.clearcoatNormalMap,1===e.side&&t.clearcoatNormalScale.value.negate()));e.iridescence>0&&(t.iridescence.value=e.iridescence,t.iridescenceIOR.value=e.iridescenceIOR,t.iridescenceThicknessMinimum.value=e.iridescenceThicknessRange[0],t.iridescenceThicknessMaximum.value=e.iridescenceThicknessRange[1],e.iridescenceMap&&(t.iridescenceMap.value=e.iridescenceMap),e.iridescenceThicknessMap&&(t.iridescenceThicknessMap.value=e.iridescenceThicknessMap));e.transmission>0&&(t.transmission.value=e.transmission,t.transmissionSamplerMap.value=i.texture,t.transmissionSamplerSize.value.set(i.width,i.height),e.transmissionMap&&(t.transmissionMap.value=e.transmissionMap),t.thickness.value=e.thickness,e.thicknessMap&&(t.thicknessMap.value=e.thicknessMap),t.attenuationDistance.value=e.attenuationDistance,t.attenuationColor.value.copy(e.attenuationColor));t.specularIntensity.value=e.specularIntensity,t.specularColor.value.copy(e.specularColor),e.specularIntensityMap&&(t.specularIntensityMap.value=e.specularIntensityMap);e.specularColorMap&&(t.specularColorMap.value=e.specularColorMap)}(t,n,a)):n.isMeshMatcapMaterial?(i(t,n),function(t,e){e.matcap&&(t.matcap.value=e.matcap)}(t,n)):n.isMeshDepthMaterial?i(t,n):n.isMeshDistanceMaterial?(i(t,n),function(t,e){t.referencePosition.value.copy(e.referencePosition),t.nearDistance.value=e.nearDistance,t.farDistance.value=e.farDistance}(t,n)):n.isMeshNormalMaterial?i(t,n):n.isLineBasicMaterial?(function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity}(t,n),n.isLineDashedMaterial&&function(t,e){t.dashSize.value=e.dashSize,t.totalSize.value=e.dashSize+e.gapSize,t.scale.value=e.scale}(t,n)):n.isPointsMaterial?function(t,e,i,n){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,t.size.value=e.size*i,t.scale.value=.5*n,e.map&&(t.map.value=e.map);e.alphaMap&&(t.alphaMap.value=e.alphaMap);e.alphaTest>0&&(t.alphaTest.value=e.alphaTest);let r;e.map?r=e.map:e.alphaMap&&(r=e.alphaMap);void 0!==r&&(!0===r.matrixAutoUpdate&&r.updateMatrix(),t.uvTransform.value.copy(r.matrix))}(t,n,r,s):n.isSpriteMaterial?function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,t.rotation.value=e.rotation,e.map&&(t.map.value=e.map);e.alphaMap&&(t.alphaMap.value=e.alphaMap);e.alphaTest>0&&(t.alphaTest.value=e.alphaTest);let i;e.map?i=e.map:e.alphaMap&&(i=e.alphaMap);void 0!==i&&(!0===i.matrixAutoUpdate&&i.updateMatrix(),t.uvTransform.value.copy(i.matrix))}(t,n):n.isShadowMaterial?(t.color.value.copy(n.color),t.opacity.value=n.opacity):n.isShaderMaterial&&(n.uniformsNeedUpdate=!1)}}}function ea(t,e,i,n){let r={},s={},a=[];const o=i.isWebGL2?t.getParameter(35375):0;function l(t,e,i){const n=t.value;if(void 0===i[e])return i[e]="number"==typeof n?n:n.clone(),!0;if("number"==typeof n){if(i[e]!==n)return i[e]=n,!0}else{const t=i[e];if(!1===t.equals(n))return t.copy(n),!0}return!1}function c(t){const e=t.value,i={boundary:0,storage:0};return"number"==typeof e?(i.boundary=4,i.storage=4):e.isVector2?(i.boundary=8,i.storage=8):e.isVector3||e.isColor?(i.boundary=16,i.storage=12):e.isVector4?(i.boundary=16,i.storage=16):e.isMatrix3?(i.boundary=48,i.storage=48):e.isMatrix4?(i.boundary=64,i.storage=64):e.isTexture?console.warn("THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group."):console.warn("THREE.WebGLRenderer: Unsupported uniform value type.",e),i}function h(e){const i=e.target;i.removeEventListener("dispose",h);const n=a.indexOf(i.__bindingPointIndex);a.splice(n,1),t.deleteBuffer(r[i.id]),delete r[i.id],delete s[i.id]}return{bind:function(t,e){const i=e.program;n.uniformBlockBinding(t,i)},update:function(i,u){let d=r[i.id];void 0===d&&(!function(t){const e=t.uniforms;let i=0;const n=16;let r=0;for(let t=0,s=e.length;t0){r=i%n;const t=n-r;0!==r&&t-a.boundary<0&&(i+=n-r,s.__offset=i)}i+=a.storage}r=i%n,r>0&&(i+=n-r);t.__size=i,t.__cache={}}(i),d=function(e){const i=function(){for(let t=0;t0?dt.updateCameraProjectionMatricesUniform(t,R):R.setValue(yt,"projectionMatrix",t.projectionMatrix),Z.logarithmicDepthBuffer&&R.setValue(yt,"logDepthBufFC",2/(Math.log(t.far+1)/Math.LN2)),E!==t&&(E=t,C=!0,L=!0),n.isShaderMaterial||n.isMeshPhongMaterial||n.isMeshToonMaterial||n.isMeshStandardMaterial||n.envMap){const e=R.map.cameraPosition;void 0!==e&&e.setValue(yt,j.setFromMatrixPosition(t.matrixWorld))}(n.isMeshPhongMaterial||n.isMeshToonMaterial||n.isMeshLambertMaterial||n.isMeshBasicMaterial||n.isMeshStandardMaterial||n.isShaderMaterial)&&R.setValue(yt,"isOrthographic",!0===t.isOrthographicCamera),(n.isMeshPhongMaterial||n.isMeshToonMaterial||n.isMeshLambertMaterial||n.isMeshBasicMaterial||n.isMeshStandardMaterial||n.isShaderMaterial||n.isShadowMaterial||r.isSkinnedMesh)&&(w.numMultiviewViews>0?dt.updateCameraViewMatricesUniform(t,R):R.setValue(yt,"viewMatrix",t.matrixWorldInverse))}if(r.isSkinnedMesh){R.setOptional(yt,r,"bindMatrix"),R.setOptional(yt,r,"bindMatrixInverse");const t=r.skeleton;t&&(Z.floatVertexTextures?(null===t.boneTexture&&t.computeBoneTexture(),R.setValue(yt,"boneTexture",t.boneTexture,Q),R.setValue(yt,"boneTextureSize",t.boneTextureSize)):console.warn("THREE.WebGLRenderer: SkinnedMesh can only be used with WebGL 2. With WebGL 1 OES_texture_float and vertex textures support is required."))}const N=i.morphAttributes;(void 0!==N.position||void 0!==N.normal||void 0!==N.color&&!0===Z.isWebGL2)&&mt.update(r,i,n,w);(C||y.receiveShadow!==r.receiveShadow)&&(y.receiveShadow=r.receiveShadow,R.setValue(yt,"receiveShadow",r.receiveShadow));n.isMeshGouraudMaterial&&null!==n.envMap&&(P.envMap.value=l,P.flipEnvMap.value=l.isCubeTexture&&!1===l.isRenderTargetTexture?-1:1);C&&(R.setValue(yt,"toneMappingExposure",g.toneMappingExposure),y.needsLights&&(z=L,(O=P).ambientLightColor.needsUpdate=z,O.lightProbe.needsUpdate=z,O.directionalLights.needsUpdate=z,O.directionalLightShadows.needsUpdate=z,O.pointLights.needsUpdate=z,O.pointLightShadows.needsUpdate=z,O.spotLights.needsUpdate=z,O.spotLightShadows.needsUpdate=z,O.rectAreaLights.needsUpdate=z,O.hemisphereLights.needsUpdate=z),s&&!0===n.fog&&ot.refreshFogUniforms(P,s),ot.refreshMaterialUniforms(P,n,D,I,V),ss.upload(yt,y.uniformsList,P,Q));var O,z;n.isShaderMaterial&&!0===n.uniformsNeedUpdate&&(ss.upload(yt,y.uniformsList,P,Q),n.uniformsNeedUpdate=!1);n.isSpriteMaterial&&R.setValue(yt,"center",r.center);w.numMultiviewViews>0?dt.updateObjectMatricesUniforms(r,t,R):(R.setValue(yt,"modelViewMatrix",r.modelViewMatrix),R.setValue(yt,"normalMatrix",r.normalMatrix));if(R.setValue(yt,"modelMatrix",r.matrixWorld),n.isShaderMaterial||n.isRawShaderMaterial){const t=n.uniformsGroups;for(let e=0,i=t.length;e0&&function(t,e,i){const n=Z.isWebGL2;null===V&&(V=new te(1,1,{generateMipmaps:!0,type:Y.has("EXT_color_buffer_half_float")?b:x,minFilter:v,samples:n&&!0===s?4:0}));g.getDrawingBufferSize(W),n?V.setSize(W.x,W.y):V.setSize(Tt(W.x),Tt(W.y));const r=g.getRenderTarget();g.setRenderTarget(V),g.clear();const a=g.toneMapping;g.toneMapping=0,Ut(t,e,i),g.toneMapping=a,Q.updateMultisampleRenderTarget(V),Q.updateRenderTargetMipmap(V),g.setRenderTarget(r)}(r,e,i),n&&J.viewport(C.copy(n)),r.length>0&&Ut(r,e,i),a.length>0&&Ut(a,e,i),o.length>0&&Ut(o,e,i),J.buffers.depth.setTest(!0),J.buffers.depth.setMask(!0),J.buffers.color.setMask(!0),J.setPolygonOffset(!1)}function Ut(t,e,i){const n=!0===e.isScene?e.overrideMaterial:null;for(let r=0,s=t.length;r0?f[f.length-1]:null,m.pop(),d=m.length>0?m[m.length-1]:null},this.setTexture2D=(Gt=!1,function(t,e){t&&t.isWebGLRenderTarget&&(Gt||(console.warn("THREE.WebGLRenderer.setTexture2D: don't use render targets as textures. Use their .texture property instead."),Gt=!0),t=t.texture),Q.setTexture2D(t,e)}),this.getActiveCubeFace=function(){return y},this.getActiveMipmapLevel=function(){return w},this.getRenderTarget=function(){return T},this.setRenderTargetTextures=function(t,e,i){$.get(t.texture).__webglTexture=e,$.get(t.depthTexture).__webglTexture=i;const n=$.get(t);n.__hasExternalTextures=!0,n.__autoAllocateDepthBuffer=void 0===i,n.__autoAllocateDepthBuffer||T.isWebGLMultiviewRenderTarget||!0===Y.has("WEBGL_multisampled_render_to_texture")&&(console.warn("THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided"),n.__useRenderToTexture=!1)},this.setRenderTargetFramebuffer=function(t,e){const i=$.get(t);i.__webglFramebuffer=e,i.__useDefaultFramebuffer=void 0===e},this.setRenderTarget=function(t,e=0,i=0){T=t,y=e,w=i;let n=!0,r=null,s=!1,a=!1;if(t){const i=$.get(t);void 0!==i.__useDefaultFramebuffer?(J.bindFramebuffer(36160,null),n=!1):void 0===i.__webglFramebuffer?Q.setupRenderTarget(t):i.__hasExternalTextures&&Q.rebindTextures(t,$.get(t.texture).__webglTexture,$.get(t.depthTexture).__webglTexture);const o=t.texture;(o.isData3DTexture||o.isDataArrayTexture||o.isCompressedArrayTexture)&&(a=!0);const l=$.get(t).__webglFramebuffer;t.isWebGLCubeRenderTarget?(r=l[e],s=!0):r=Z.isWebGL2&&t.samples>0&&!1===Q.useMultisampledRTT(t)?$.get(t).__webglMultisampledFramebuffer:l,C.copy(t.viewport),L.copy(t.scissor),R=t.scissorTest}else C.copy(z).multiplyScalar(D).floor(),L.copy(U).multiplyScalar(D).floor(),R=B;if(J.bindFramebuffer(36160,r)&&Z.drawBuffers&&n&&J.drawBuffers(t,r),J.viewport(C),J.scissor(L),J.setScissorTest(R),s){const n=$.get(t.texture);yt.framebufferTexture2D(36160,36064,34069+e,n.__webglTexture,i)}else if(a){const n=$.get(t.texture),r=e||0;yt.framebufferTextureLayer(36160,36064,n.__webglTexture,i||0,r)}A=-1},this.readRenderTargetPixels=function(t,e,i,n,r,s,a){if(!t||!t.isWebGLRenderTarget)return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let o=$.get(t).__webglFramebuffer;if(t.isWebGLCubeRenderTarget&&void 0!==a&&(o=o[a]),o){J.bindFramebuffer(36160,o);try{const a=t.texture,o=a.format,l=a.type;if(o!==S&&vt.convert(o)!==yt.getParameter(35739))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");const c=l===b&&(Y.has("EXT_color_buffer_half_float")||Z.isWebGL2&&Y.has("EXT_color_buffer_float"));if(!(l===x||vt.convert(l)===yt.getParameter(35738)||l===M&&(Z.isWebGL2||Y.has("OES_texture_float")||Y.has("WEBGL_color_buffer_float"))||c))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");e>=0&&e<=t.width-n&&i>=0&&i<=t.height-r&&yt.readPixels(e,i,n,r,vt.convert(o),vt.convert(l),s)}finally{const t=null!==T?$.get(T).__webglFramebuffer:null;J.bindFramebuffer(36160,t)}}},this.copyFramebufferToTexture=function(t,e,i=0){const n=Math.pow(2,-i),r=Math.floor(e.image.width*n),s=Math.floor(e.image.height*n);Q.setTexture2D(e,0),yt.copyTexSubImage2D(3553,i,0,0,t.x,t.y,r,s),J.unbindTexture()},this.copyTextureToTexture=function(t,e,i,n=0){const r=e.image.width,s=e.image.height,a=vt.convert(i.format),o=vt.convert(i.type);Q.setTexture2D(i,0),yt.pixelStorei(37440,i.flipY),yt.pixelStorei(37441,i.premultiplyAlpha),yt.pixelStorei(3317,i.unpackAlignment),e.isDataTexture?yt.texSubImage2D(3553,n,t.x,t.y,r,s,a,o,e.image.data):e.isCompressedTexture?yt.compressedTexSubImage2D(3553,n,t.x,t.y,e.mipmaps[0].width,e.mipmaps[0].height,a,e.mipmaps[0].data):yt.texSubImage2D(3553,n,t.x,t.y,a,o,e.image),0===n&&i.generateMipmaps&&yt.generateMipmap(3553),J.unbindTexture()},this.copyTextureToTexture3D=function(t,e,i,n,r=0){if(g.isWebGL1Renderer)return void console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.");const s=t.max.x-t.min.x+1,a=t.max.y-t.min.y+1,o=t.max.z-t.min.z+1,l=vt.convert(n.format),c=vt.convert(n.type);let h;if(n.isData3DTexture)Q.setTexture3D(n,0),h=32879;else{if(!n.isDataArrayTexture)return void console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.");Q.setTexture2DArray(n,0),h=35866}yt.pixelStorei(37440,n.flipY),yt.pixelStorei(37441,n.premultiplyAlpha),yt.pixelStorei(3317,n.unpackAlignment);const u=yt.getParameter(3314),d=yt.getParameter(32878),p=yt.getParameter(3316),m=yt.getParameter(3315),f=yt.getParameter(32877),v=i.isCompressedTexture?i.mipmaps[0]:i.image;yt.pixelStorei(3314,v.width),yt.pixelStorei(32878,v.height),yt.pixelStorei(3316,t.min.x),yt.pixelStorei(3315,t.min.y),yt.pixelStorei(32877,t.min.z),i.isDataTexture||i.isData3DTexture?yt.texSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,c,v.data):i.isCompressedArrayTexture?(console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture."),yt.compressedTexSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,v.data)):yt.texSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,c,v),yt.pixelStorei(3314,u),yt.pixelStorei(32878,d),yt.pixelStorei(3316,p),yt.pixelStorei(3315,m),yt.pixelStorei(32877,f),0===r&&n.generateMipmaps&&yt.generateMipmap(h),J.unbindTexture()},this.initTexture=function(t){t.isCubeTexture?Q.setTextureCube(t,0):t.isData3DTexture?Q.setTexture3D(t,0):t.isDataArrayTexture||t.isCompressedArrayTexture?Q.setTexture2DArray(t,0):Q.setTexture2D(t,0),J.unbindTexture()},this.resetState=function(){y=0,w=0,T=null,J.reset(),xt.reset()},"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}class na extends ia{}na.prototype.isWebGL1Renderer=!0;class ra{constructor(t,e=25e-5){this.isFogExp2=!0,this.name="",this.color=new qt(t),this.density=e}clone(){return new ra(this.color,this.density)}toJSON(){return{type:"FogExp2",color:this.color.getHex(),density:this.density}}}class sa{constructor(t,e=1,i=1e3){this.isFog=!0,this.name="",this.color=new qt(t),this.near=e,this.far=i}clone(){return new sa(this.color,this.near,this.far)}toJSON(){return{type:"Fog",color:this.color.getHex(),near:this.near,far:this.far}}}class aa extends si{constructor(){super(),this.isScene=!0,this.type="Scene",this.background=null,this.environment=null,this.fog=null,this.backgroundBlurriness=0,this.backgroundIntensity=1,this.overrideMaterial=null,"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}copy(t,e){return super.copy(t,e),null!==t.background&&(this.background=t.background.clone()),null!==t.environment&&(this.environment=t.environment.clone()),null!==t.fog&&(this.fog=t.fog.clone()),this.backgroundBlurriness=t.backgroundBlurriness,this.backgroundIntensity=t.backgroundIntensity,null!==t.overrideMaterial&&(this.overrideMaterial=t.overrideMaterial.clone()),this.matrixAutoUpdate=t.matrixAutoUpdate,this}toJSON(t){const e=super.toJSON(t);return null!==this.fog&&(e.object.fog=this.fog.toJSON()),this.backgroundBlurriness>0&&(e.backgroundBlurriness=this.backgroundBlurriness),1!==this.backgroundIntensity&&(e.backgroundIntensity=this.backgroundIntensity),e}get autoUpdate(){return console.warn("THREE.Scene: autoUpdate was renamed to matrixWorldAutoUpdate in r144."),this.matrixWorldAutoUpdate}set autoUpdate(t){console.warn("THREE.Scene: autoUpdate was renamed to matrixWorldAutoUpdate in r144."),this.matrixWorldAutoUpdate=t}}class oa{constructor(t,e){this.isInterleavedBuffer=!0,this.array=t,this.stride=e,this.count=void 0!==t?t.length/e:0,this.usage=ut,this.updateRange={offset:0,count:-1},this.version=0,this.uuid=_t()}onUploadCallback(){}set needsUpdate(t){!0===t&&this.version++}setUsage(t){return this.usage=t,this}copy(t){return this.array=new t.array.constructor(t.array),this.count=t.count,this.stride=t.stride,this.usage=t.usage,this}copyAt(t,e,i){t*=this.stride,i*=e.stride;for(let n=0,r=this.stride;nt.far||e.push({distance:o,point:da.clone(),uv:gi.getUV(da,xa,_a,ya,Ma,ba,wa,new Lt),face:null,object:this})}copy(t,e){return super.copy(t,e),void 0!==t.center&&this.center.copy(t.center),this.material=t.material,this}}function Ta(t,e,i,n,r,s){fa.subVectors(t,i).addScalar(.5).multiply(n),void 0!==r?(ga.x=s*fa.x-r*fa.y,ga.y=r*fa.x+s*fa.y):ga.copy(fa),t.copy(e),t.x+=ga.x,t.y+=ga.y,t.applyMatrix4(va)}const Aa=new re,Ea=new re;class Ca extends si{constructor(){super(),this._currentLevel=0,this.type="LOD",Object.defineProperties(this,{levels:{enumerable:!0,value:[]},isLOD:{value:!0}}),this.autoUpdate=!0}copy(t){super.copy(t,!1);const e=t.levels;for(let t=0,i=e.length;t0){let i,n;for(i=1,n=e.length;i0){Aa.setFromMatrixPosition(this.matrixWorld);const i=t.ray.origin.distanceTo(Aa);this.getObjectForDistance(i).raycast(t,e)}}update(t){const e=this.levels;if(e.length>1){Aa.setFromMatrixPosition(t.matrixWorld),Ea.setFromMatrixPosition(this.matrixWorld);const i=Aa.distanceTo(Ea)/t.zoom;let n,r;for(e[0].object.visible=!0,n=1,r=e.length;n=t))break;e[n-1].object.visible=!1,e[n].object.visible=!0}for(this._currentLevel=n-1;no)continue;u.applyMatrix4(this.matrixWorld);const s=t.ray.origin.distanceTo(u);st.far||e.push({distance:s,point:h.clone().applyMatrix4(this.matrixWorld),index:i,face:null,faceIndex:null,object:this})}}else{for(let i=Math.max(0,s.start),n=Math.min(m.count,s.start+s.count)-1;io)continue;u.applyMatrix4(this.matrixWorld);const n=t.ray.origin.distanceTo(u);nt.far||e.push({distance:n,point:h.clone().applyMatrix4(this.matrixWorld),index:i,face:null,faceIndex:null,object:this})}}}updateMorphTargets(){const t=this.geometry.morphAttributes,e=Object.keys(t);if(e.length>0){const i=t[e[0]];if(void 0!==i){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=i.length;t0){const i=t[e[0]];if(void 0!==i){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=i.length;tr.far)return;s.push({distance:l,distanceToRay:Math.sqrt(o),point:i,index:e,face:null,object:a})}}class uo extends $t{constructor(t,e,i,n,r,s,a,o,l,c,h,u){super(null,s,a,o,l,c,n,r,h,u),this.isCompressedTexture=!0,this.image={width:e,height:i},this.mipmaps=t,this.flipY=!1,this.generateMipmaps=!1}}class po{constructor(){this.type="Curve",this.arcLengthDivisions=200}getPoint(){return console.warn("THREE.Curve: .getPoint() not implemented."),null}getPointAt(t,e){const i=this.getUtoTmapping(t);return this.getPoint(i,e)}getPoints(t=5){const e=[];for(let i=0;i<=t;i++)e.push(this.getPoint(i/t));return e}getSpacedPoints(t=5){const e=[];for(let i=0;i<=t;i++)e.push(this.getPointAt(i/t));return e}getLength(){const t=this.getLengths();return t[t.length-1]}getLengths(t=this.arcLengthDivisions){if(this.cacheArcLengths&&this.cacheArcLengths.length===t+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=!1;const e=[];let i,n=this.getPoint(0),r=0;e.push(0);for(let s=1;s<=t;s++)i=this.getPoint(s/t),r+=i.distanceTo(n),e.push(r),n=i;return this.cacheArcLengths=e,e}updateArcLengths(){this.needsUpdate=!0,this.getLengths()}getUtoTmapping(t,e){const i=this.getLengths();let n=0;const r=i.length;let s;s=e||t*i[r-1];let a,o=0,l=r-1;for(;o<=l;)if(n=Math.floor(o+(l-o)/2),a=i[n]-s,a<0)o=n+1;else{if(!(a>0)){l=n;break}l=n-1}if(n=l,i[n]===s)return n/(r-1);const c=i[n];return(n+(s-c)/(i[n+1]-c))/(r-1)}getTangent(t,e){const i=1e-4;let n=t-i,r=t+i;n<0&&(n=0),r>1&&(r=1);const s=this.getPoint(n),a=this.getPoint(r),o=e||(s.isVector2?new Lt:new re);return o.copy(a).sub(s).normalize(),o}getTangentAt(t,e){const i=this.getUtoTmapping(t);return this.getTangent(i,e)}computeFrenetFrames(t,e){const i=new re,n=[],r=[],s=[],a=new re,o=new Ne;for(let e=0;e<=t;e++){const i=e/t;n[e]=this.getTangentAt(i,new re)}r[0]=new re,s[0]=new re;let l=Number.MAX_VALUE;const c=Math.abs(n[0].x),h=Math.abs(n[0].y),u=Math.abs(n[0].z);c<=l&&(l=c,i.set(1,0,0)),h<=l&&(l=h,i.set(0,1,0)),u<=l&&i.set(0,0,1),a.crossVectors(n[0],i).normalize(),r[0].crossVectors(n[0],a),s[0].crossVectors(n[0],r[0]);for(let e=1;e<=t;e++){if(r[e]=r[e-1].clone(),s[e]=s[e-1].clone(),a.crossVectors(n[e-1],n[e]),a.length()>Number.EPSILON){a.normalize();const t=Math.acos(yt(n[e-1].dot(n[e]),-1,1));r[e].applyMatrix4(o.makeRotationAxis(a,t))}s[e].crossVectors(n[e],r[e])}if(!0===e){let e=Math.acos(yt(r[0].dot(r[t]),-1,1));e/=t,n[0].dot(a.crossVectors(r[0],r[t]))>0&&(e=-e);for(let i=1;i<=t;i++)r[i].applyMatrix4(o.makeRotationAxis(n[i],e*i)),s[i].crossVectors(n[i],r[i])}return{tangents:n,normals:r,binormals:s}}clone(){return(new this.constructor).copy(this)}copy(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}toJSON(){const t={metadata:{version:4.5,type:"Curve",generator:"Curve.toJSON"}};return t.arcLengthDivisions=this.arcLengthDivisions,t.type=this.type,t}fromJSON(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}}class mo extends po{constructor(t=0,e=0,i=1,n=1,r=0,s=2*Math.PI,a=!1,o=0){super(),this.isEllipseCurve=!0,this.type="EllipseCurve",this.aX=t,this.aY=e,this.xRadius=i,this.yRadius=n,this.aStartAngle=r,this.aEndAngle=s,this.aClockwise=a,this.aRotation=o}getPoint(t,e){const i=e||new Lt,n=2*Math.PI;let r=this.aEndAngle-this.aStartAngle;const s=Math.abs(r)n;)r-=n;r0?0:(Math.floor(Math.abs(l)/r)+1)*r:0===c&&l===r-1&&(l=r-2,c=1),this.closed||l>0?a=n[(l-1)%r]:(vo.subVectors(n[0],n[1]).add(n[0]),a=vo);const h=n[l%r],u=n[(l+1)%r];if(this.closed||l+2n.length-2?n.length-1:s+1],h=n[s>n.length-3?n.length-1:s+2];return i.set(bo(a,o.x,l.x,c.x,h.x),bo(a,o.y,l.y,c.y,h.y)),i}copy(t){super.copy(t),this.points=[];for(let e=0,i=t.points.length;e=i){const t=n[r]-i,s=this.curves[r],a=s.getLength(),o=0===a?0:1-t/a;return s.getPointAt(o,e)}r++}return null}getLength(){const t=this.getCurveLengths();return t[t.length-1]}updateArcLengths(){this.needsUpdate=!0,this.cacheLengths=null,this.getCurveLengths()}getCurveLengths(){if(this.cacheLengths&&this.cacheLengths.length===this.curves.length)return this.cacheLengths;const t=[];let e=0;for(let i=0,n=this.curves.length;i1&&!e[e.length-1].equals(e[0])&&e.push(e[0]),e}copy(t){super.copy(t),this.curves=[];for(let e=0,i=t.curves.length;e0){const t=l.getPoint(0);t.equals(this.currentPoint)||this.lineTo(t.x,t.y)}this.curves.push(l);const c=l.getPoint(1);return this.currentPoint.copy(c),this}copy(t){return super.copy(t),this.currentPoint.copy(t.currentPoint),this}toJSON(){const t=super.toJSON();return t.currentPoint=this.currentPoint.toArray(),t}fromJSON(t){return super.fromJSON(t),this.currentPoint.fromArray(t.currentPoint),this}}class Oo extends Di{constructor(t=[new Lt(0,-.5),new Lt(.5,0),new Lt(0,.5)],e=12,i=0,n=2*Math.PI){super(),this.type="LatheGeometry",this.parameters={points:t,segments:e,phiStart:i,phiLength:n},e=Math.floor(e),n=yt(n,0,2*Math.PI);const r=[],s=[],a=[],o=[],l=[],c=1/e,h=new re,u=new Lt,d=new re,p=new re,m=new re;let f=0,g=0;for(let e=0;e<=t.length-1;e++)switch(e){case 0:f=t[e+1].x-t[e].x,g=t[e+1].y-t[e].y,d.x=1*g,d.y=-f,d.z=0*g,m.copy(d),d.normalize(),o.push(d.x,d.y,d.z);break;case t.length-1:o.push(m.x,m.y,m.z);break;default:f=t[e+1].x-t[e].x,g=t[e+1].y-t[e].y,d.x=1*g,d.y=-f,d.z=0*g,p.copy(d),d.x+=m.x,d.y+=m.y,d.z+=m.z,d.normalize(),o.push(d.x,d.y,d.z),m.copy(p)}for(let r=0;r<=e;r++){const d=i+r*c*n,p=Math.sin(d),m=Math.cos(d);for(let i=0;i<=t.length-1;i++){h.x=t[i].x*p,h.y=t[i].y,h.z=t[i].x*m,s.push(h.x,h.y,h.z),u.x=r/e,u.y=i/(t.length-1),a.push(u.x,u.y);const n=o[3*i+0]*p,c=o[3*i+1],d=o[3*i+0]*m;l.push(n,c,d)}}for(let i=0;i0&&v(!0),e>0&&v(!1)),this.setIndex(c),this.setAttribute("position",new Ti(h,3)),this.setAttribute("normal",new Ti(u,3)),this.setAttribute("uv",new Ti(d,2))}static fromJSON(t){return new Bo(t.radiusTop,t.radiusBottom,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class Fo extends Bo{constructor(t=1,e=1,i=8,n=1,r=!1,s=0,a=2*Math.PI){super(0,t,e,i,n,r,s,a),this.type="ConeGeometry",this.parameters={radius:t,height:e,radialSegments:i,heightSegments:n,openEnded:r,thetaStart:s,thetaLength:a}}static fromJSON(t){return new Fo(t.radius,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class ko extends Di{constructor(t=[],e=[],i=1,n=0){super(),this.type="PolyhedronGeometry",this.parameters={vertices:t,indices:e,radius:i,detail:n};const r=[],s=[];function a(t,e,i,n){const r=n+1,s=[];for(let n=0;n<=r;n++){s[n]=[];const a=t.clone().lerp(i,n/r),o=e.clone().lerp(i,n/r),l=r-n;for(let t=0;t<=l;t++)s[n][t]=0===t&&n===r?a:a.clone().lerp(o,t/l)}for(let t=0;t.9&&a<.1&&(e<.2&&(s[t+0]+=1),i<.2&&(s[t+2]+=1),n<.2&&(s[t+4]+=1))}}()}(),this.setAttribute("position",new Ti(r,3)),this.setAttribute("normal",new Ti(r.slice(),3)),this.setAttribute("uv",new Ti(s,2)),0===n?this.computeVertexNormals():this.normalizeNormals()}static fromJSON(t){return new ko(t.vertices,t.indices,t.radius,t.details)}}class Go extends ko{constructor(t=1,e=0){const i=(1+Math.sqrt(5))/2,n=1/i;super([-1,-1,-1,-1,-1,1,-1,1,-1,-1,1,1,1,-1,-1,1,-1,1,1,1,-1,1,1,1,0,-n,-i,0,-n,i,0,n,-i,0,n,i,-n,-i,0,-n,i,0,n,-i,0,n,i,0,-i,0,-n,i,0,-n,-i,0,n,i,0,n],[3,11,7,3,7,15,3,15,13,7,19,17,7,17,6,7,6,15,17,4,8,17,8,10,17,10,6,8,0,16,8,16,2,8,2,10,0,12,1,0,1,18,0,18,16,6,10,2,6,2,13,6,13,15,2,16,18,2,18,3,2,3,13,18,1,9,18,9,11,18,11,3,4,14,12,4,12,0,4,0,8,11,9,5,11,5,19,11,19,7,19,5,14,19,14,4,19,4,17,1,12,14,1,14,5,1,5,9],t,e),this.type="DodecahedronGeometry",this.parameters={radius:t,detail:e}}static fromJSON(t){return new Go(t.radius,t.detail)}}const Vo=new re,Ho=new re,Wo=new re,jo=new gi;class qo extends Di{constructor(t=null,e=1){if(super(),this.type="EdgesGeometry",this.parameters={geometry:t,thresholdAngle:e},null!==t){const i=4,n=Math.pow(10,i),r=Math.cos(vt*e),s=t.getIndex(),a=t.getAttribute("position"),o=s?s.count:a.count,l=[0,0,0],c=["a","b","c"],h=new Array(3),u={},d=[];for(let t=0;t80*i){o=c=t[0],l=h=t[1];for(let e=i;ec&&(c=u),d>h&&(h=d);p=Math.max(c-o,h-l),p=0!==p?32767/p:0}return Ko(s,a,i,o,l,p,0),a};function Zo(t,e,i,n,r){let s,a;if(r===function(t,e,i,n){let r=0;for(let s=e,a=i-n;s0)for(s=e;s=e;s-=n)a=gl(s,t[s],t[s+1],a);return a&&hl(a,a.next)&&(vl(a),a=a.next),a}function Jo(t,e){if(!t)return t;e||(e=t);let i,n=t;do{if(i=!1,n.steiner||!hl(n,n.next)&&0!==cl(n.prev,n,n.next))n=n.next;else{if(vl(n),n=e=n.prev,n===n.next)break;i=!0}}while(i||n!==e);return e}function Ko(t,e,i,n,r,s,a){if(!t)return;!a&&s&&function(t,e,i,n){let r=t;do{0===r.z&&(r.z=sl(r.x,r.y,e,i,n)),r.prevZ=r.prev,r.nextZ=r.next,r=r.next}while(r!==t);r.prevZ.nextZ=null,r.prevZ=null,function(t){let e,i,n,r,s,a,o,l,c=1;do{for(i=t,t=null,s=null,a=0;i;){for(a++,n=i,o=0,e=0;e0||l>0&&n;)0!==o&&(0===l||!n||i.z<=n.z)?(r=i,i=i.nextZ,o--):(r=n,n=n.nextZ,l--),s?s.nextZ=r:t=r,r.prevZ=s,s=r;i=n}s.nextZ=null,c*=2}while(a>1)}(r)}(t,n,r,s);let o,l,c=t;for(;t.prev!==t.next;)if(o=t.prev,l=t.next,s?Qo(t,n,r,s):$o(t))e.push(o.i/i|0),e.push(t.i/i|0),e.push(l.i/i|0),vl(t),t=l.next,c=l.next;else if((t=l)===c){a?1===a?Ko(t=tl(Jo(t),e,i),e,i,n,r,s,2):2===a&&el(t,e,i,n,r,s):Ko(Jo(t),e,i,n,r,s,1);break}}function $o(t){const e=t.prev,i=t,n=t.next;if(cl(e,i,n)>=0)return!1;const r=e.x,s=i.x,a=n.x,o=e.y,l=i.y,c=n.y,h=rs?r>a?r:a:s>a?s:a,p=o>l?o>c?o:c:l>c?l:c;let m=n.next;for(;m!==e;){if(m.x>=h&&m.x<=d&&m.y>=u&&m.y<=p&&ol(r,o,s,l,a,c,m.x,m.y)&&cl(m.prev,m,m.next)>=0)return!1;m=m.next}return!0}function Qo(t,e,i,n){const r=t.prev,s=t,a=t.next;if(cl(r,s,a)>=0)return!1;const o=r.x,l=s.x,c=a.x,h=r.y,u=s.y,d=a.y,p=ol?o>c?o:c:l>c?l:c,g=h>u?h>d?h:d:u>d?u:d,v=sl(p,m,e,i,n),x=sl(f,g,e,i,n);let _=t.prevZ,y=t.nextZ;for(;_&&_.z>=v&&y&&y.z<=x;){if(_.x>=p&&_.x<=f&&_.y>=m&&_.y<=g&&_!==r&&_!==a&&ol(o,h,l,u,c,d,_.x,_.y)&&cl(_.prev,_,_.next)>=0)return!1;if(_=_.prevZ,y.x>=p&&y.x<=f&&y.y>=m&&y.y<=g&&y!==r&&y!==a&&ol(o,h,l,u,c,d,y.x,y.y)&&cl(y.prev,y,y.next)>=0)return!1;y=y.nextZ}for(;_&&_.z>=v;){if(_.x>=p&&_.x<=f&&_.y>=m&&_.y<=g&&_!==r&&_!==a&&ol(o,h,l,u,c,d,_.x,_.y)&&cl(_.prev,_,_.next)>=0)return!1;_=_.prevZ}for(;y&&y.z<=x;){if(y.x>=p&&y.x<=f&&y.y>=m&&y.y<=g&&y!==r&&y!==a&&ol(o,h,l,u,c,d,y.x,y.y)&&cl(y.prev,y,y.next)>=0)return!1;y=y.nextZ}return!0}function tl(t,e,i){let n=t;do{const r=n.prev,s=n.next.next;!hl(r,s)&&ul(r,n,n.next,s)&&ml(r,s)&&ml(s,r)&&(e.push(r.i/i|0),e.push(n.i/i|0),e.push(s.i/i|0),vl(n),vl(n.next),n=t=s),n=n.next}while(n!==t);return Jo(n)}function el(t,e,i,n,r,s){let a=t;do{let t=a.next.next;for(;t!==a.prev;){if(a.i!==t.i&&ll(a,t)){let o=fl(a,t);return a=Jo(a,a.next),o=Jo(o,o.next),Ko(a,e,i,n,r,s,0),void Ko(o,e,i,n,r,s,0)}t=t.next}a=a.next}while(a!==t)}function il(t,e){return t.x-e.x}function nl(t,e){const i=function(t,e){let i,n=e,r=-1/0;const s=t.x,a=t.y;do{if(a<=n.y&&a>=n.next.y&&n.next.y!==n.y){const t=n.x+(a-n.y)*(n.next.x-n.x)/(n.next.y-n.y);if(t<=s&&t>r&&(r=t,i=n.x=n.x&&n.x>=l&&s!==n.x&&ol(ai.x||n.x===i.x&&rl(i,n)))&&(i=n,u=h)),n=n.next}while(n!==o);return i}(t,e);if(!i)return e;const n=fl(i,t);return Jo(n,n.next),Jo(i,i.next)}function rl(t,e){return cl(t.prev,t,e.prev)<0&&cl(e.next,t,t.next)<0}function sl(t,e,i,n,r){return(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=(t-i)*r|0)|t<<8))|t<<4))|t<<2))|t<<1))|(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=(e-n)*r|0)|e<<8))|e<<4))|e<<2))|e<<1))<<1}function al(t){let e=t,i=t;do{(e.x=(t-a)*(s-o)&&(t-a)*(n-o)>=(i-a)*(e-o)&&(i-a)*(s-o)>=(r-a)*(n-o)}function ll(t,e){return t.next.i!==e.i&&t.prev.i!==e.i&&!function(t,e){let i=t;do{if(i.i!==t.i&&i.next.i!==t.i&&i.i!==e.i&&i.next.i!==e.i&&ul(i,i.next,t,e))return!0;i=i.next}while(i!==t);return!1}(t,e)&&(ml(t,e)&&ml(e,t)&&function(t,e){let i=t,n=!1;const r=(t.x+e.x)/2,s=(t.y+e.y)/2;do{i.y>s!=i.next.y>s&&i.next.y!==i.y&&r<(i.next.x-i.x)*(s-i.y)/(i.next.y-i.y)+i.x&&(n=!n),i=i.next}while(i!==t);return n}(t,e)&&(cl(t.prev,t,e.prev)||cl(t,e.prev,e))||hl(t,e)&&cl(t.prev,t,t.next)>0&&cl(e.prev,e,e.next)>0)}function cl(t,e,i){return(e.y-t.y)*(i.x-e.x)-(e.x-t.x)*(i.y-e.y)}function hl(t,e){return t.x===e.x&&t.y===e.y}function ul(t,e,i,n){const r=pl(cl(t,e,i)),s=pl(cl(t,e,n)),a=pl(cl(i,n,t)),o=pl(cl(i,n,e));return r!==s&&a!==o||(!(0!==r||!dl(t,i,e))||(!(0!==s||!dl(t,n,e))||(!(0!==a||!dl(i,t,n))||!(0!==o||!dl(i,e,n)))))}function dl(t,e,i){return e.x<=Math.max(t.x,i.x)&&e.x>=Math.min(t.x,i.x)&&e.y<=Math.max(t.y,i.y)&&e.y>=Math.min(t.y,i.y)}function pl(t){return t>0?1:t<0?-1:0}function ml(t,e){return cl(t.prev,t,t.next)<0?cl(t,e,t.next)>=0&&cl(t,t.prev,e)>=0:cl(t,e,t.prev)<0||cl(t,t.next,e)<0}function fl(t,e){const i=new xl(t.i,t.x,t.y),n=new xl(e.i,e.x,e.y),r=t.next,s=e.prev;return t.next=e,e.prev=t,i.next=r,r.prev=i,n.next=i,i.prev=n,s.next=n,n.prev=s,n}function gl(t,e,i,n){const r=new xl(t,e,i);return n?(r.next=n.next,r.prev=n,n.next.prev=r,n.next=r):(r.prev=r,r.next=r),r}function vl(t){t.next.prev=t.prev,t.prev.next=t.next,t.prevZ&&(t.prevZ.nextZ=t.nextZ),t.nextZ&&(t.nextZ.prevZ=t.prevZ)}function xl(t,e,i){this.i=t,this.x=e,this.y=i,this.prev=null,this.next=null,this.z=0,this.prevZ=null,this.nextZ=null,this.steiner=!1}class _l{static area(t){const e=t.length;let i=0;for(let n=e-1,r=0;r2&&t[e-1].equals(t[0])&&t.pop()}function Ml(t,e){for(let i=0;iNumber.EPSILON){const u=Math.sqrt(h),d=Math.sqrt(l*l+c*c),p=e.x-o/u,m=e.y+a/u,f=((i.x-c/d-p)*c-(i.y+l/d-m)*l)/(a*c-o*l);n=p+a*f-t.x,r=m+o*f-t.y;const g=n*n+r*r;if(g<=2)return new Lt(n,r);s=Math.sqrt(g/2)}else{let t=!1;a>Number.EPSILON?l>Number.EPSILON&&(t=!0):a<-Number.EPSILON?l<-Number.EPSILON&&(t=!0):Math.sign(o)===Math.sign(c)&&(t=!0),t?(n=-o,r=a,s=Math.sqrt(h)):(n=a,r=o,s=Math.sqrt(h/2))}return new Lt(n/s,r/s)}const P=[];for(let t=0,e=A.length,i=e-1,n=t+1;t=0;t--){const e=t/p,i=h*Math.cos(e*Math.PI/2),n=u*Math.sin(e*Math.PI/2)+d;for(let t=0,e=A.length;t=0;){const n=i;let r=i-1;r<0&&(r=t.length-1);for(let t=0,i=o+2*p;t0)&&d.push(e,r,l),(t!==i-1||o0!=t>0&&this.version++,this._sheen=t}get clearcoat(){return this._clearcoat}set clearcoat(t){this._clearcoat>0!=t>0&&this.version++,this._clearcoat=t}get iridescence(){return this._iridescence}set iridescence(t){this._iridescence>0!=t>0&&this.version++,this._iridescence=t}get transmission(){return this._transmission}set transmission(t){this._transmission>0!=t>0&&this.version++,this._transmission=t}copy(t){return super.copy(t),this.defines={STANDARD:"",PHYSICAL:""},this.clearcoat=t.clearcoat,this.clearcoatMap=t.clearcoatMap,this.clearcoatRoughness=t.clearcoatRoughness,this.clearcoatRoughnessMap=t.clearcoatRoughnessMap,this.clearcoatNormalMap=t.clearcoatNormalMap,this.clearcoatNormalScale.copy(t.clearcoatNormalScale),this.ior=t.ior,this.iridescence=t.iridescence,this.iridescenceMap=t.iridescenceMap,this.iridescenceIOR=t.iridescenceIOR,this.iridescenceThicknessRange=[...t.iridescenceThicknessRange],this.iridescenceThicknessMap=t.iridescenceThicknessMap,this.sheen=t.sheen,this.sheenColor.copy(t.sheenColor),this.sheenColorMap=t.sheenColorMap,this.sheenRoughness=t.sheenRoughness,this.sheenRoughnessMap=t.sheenRoughnessMap,this.transmission=t.transmission,this.transmissionMap=t.transmissionMap,this.thickness=t.thickness,this.thicknessMap=t.thicknessMap,this.attenuationDistance=t.attenuationDistance,this.attenuationColor.copy(t.attenuationColor),this.specularIntensity=t.specularIntensity,this.specularIntensityMap=t.specularIntensityMap,this.specularColor.copy(t.specularColor),this.specularColorMap=t.specularColorMap,this}}class kl extends xi{constructor(t){super(),this.isMeshPhongMaterial=!0,this.type="MeshPhongMaterial",this.color=new qt(16777215),this.specular=new qt(1118481),this.shininess=30,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new qt(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Lt(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.specular.copy(t.specular),this.shininess=t.shininess,this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.flatShading=t.flatShading,this.fog=t.fog,this}}class Gl extends xi{constructor(t){super(),this.isMeshToonMaterial=!0,this.defines={TOON:""},this.type="MeshToonMaterial",this.color=new qt(16777215),this.map=null,this.gradientMap=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new qt(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Lt(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.gradientMap=t.gradientMap,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.alphaMap=t.alphaMap,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.fog=t.fog,this}}class Vl extends xi{constructor(t){super(),this.isMeshNormalMaterial=!0,this.type="MeshNormalMaterial",this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Lt(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.flatShading=!1,this.setValues(t)}copy(t){return super.copy(t),this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.flatShading=t.flatShading,this}}class Hl extends xi{constructor(t){super(),this.isMeshLambertMaterial=!0,this.type="MeshLambertMaterial",this.color=new qt(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new qt(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Lt(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.flatShading=t.flatShading,this.fog=t.fog,this}}class Wl extends xi{constructor(t){super(),this.isMeshMatcapMaterial=!0,this.defines={MATCAP:""},this.type="MeshMatcapMaterial",this.color=new qt(16777215),this.matcap=null,this.map=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Lt(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.defines={MATCAP:""},this.color.copy(t.color),this.matcap=t.matcap,this.map=t.map,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.alphaMap=t.alphaMap,this.flatShading=t.flatShading,this.fog=t.fog,this}}class jl extends Xa{constructor(t){super(),this.isLineDashedMaterial=!0,this.type="LineDashedMaterial",this.scale=1,this.dashSize=3,this.gapSize=1,this.setValues(t)}copy(t){return super.copy(t),this.scale=t.scale,this.dashSize=t.dashSize,this.gapSize=t.gapSize,this}}function ql(t,e,i){return Yl(t)?new t.constructor(t.subarray(e,void 0!==i?i:t.length)):t.slice(e,i)}function Xl(t,e,i){return!t||!i&&t.constructor===e?t:"number"==typeof e.BYTES_PER_ELEMENT?new e(t):Array.prototype.slice.call(t)}function Yl(t){return ArrayBuffer.isView(t)&&!(t instanceof DataView)}function Zl(t){const e=t.length,i=new Array(e);for(let t=0;t!==e;++t)i[t]=t;return i.sort((function(e,i){return t[e]-t[i]})),i}function Jl(t,e,i){const n=t.length,r=new t.constructor(n);for(let s=0,a=0;a!==n;++s){const n=i[s]*e;for(let i=0;i!==e;++i)r[a++]=t[n+i]}return r}function Kl(t,e,i,n){let r=1,s=t[0];for(;void 0!==s&&void 0===s[n];)s=t[r++];if(void 0===s)return;let a=s[n];if(void 0!==a)if(Array.isArray(a))do{a=s[n],void 0!==a&&(e.push(s.time),i.push.apply(i,a)),s=t[r++]}while(void 0!==s);else if(void 0!==a.toArray)do{a=s[n],void 0!==a&&(e.push(s.time),a.toArray(i,i.length)),s=t[r++]}while(void 0!==s);else do{a=s[n],void 0!==a&&(e.push(s.time),i.push(a)),s=t[r++]}while(void 0!==s)}var $l=Object.freeze({__proto__:null,arraySlice:ql,convertArray:Xl,isTypedArray:Yl,getKeyframeOrder:Zl,sortedArray:Jl,flattenJSON:Kl,subclip:function(t,e,i,n,r=30){const s=t.clone();s.name=e;const a=[];for(let t=0;t=n)){l.push(e.times[t]);for(let i=0;is.tracks[t].times[0]&&(o=s.tracks[t].times[0]);for(let t=0;t=n.times[u]){const t=u*l+o,e=t+l-o;d=ql(n.values,t,e)}else{const t=n.createInterpolant(),e=o,i=l-o;t.evaluate(s),d=ql(t.resultBuffer,e,i)}if("quaternion"===r){(new ne).fromArray(d).normalize().conjugate().toArray(d)}const p=a.times.length;for(let t=0;t=r)break t;{const a=e[1];t=r)break e}s=i,i=0}}for(;i>>1;te;)--s;if(++s,0!==r||s!==n){r>=s&&(s=Math.max(s,1),r=s-1);const t=this.getValueSize();this.times=ql(i,r,s),this.values=ql(this.values,r*t,s*t)}return this}validate(){let t=!0;const e=this.getValueSize();e-Math.floor(e)!=0&&(console.error("THREE.KeyframeTrack: Invalid value size in track.",this),t=!1);const i=this.times,n=this.values,r=i.length;0===r&&(console.error("THREE.KeyframeTrack: Track is empty.",this),t=!1);let s=null;for(let e=0;e!==r;e++){const n=i[e];if("number"==typeof n&&isNaN(n)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,e,n),t=!1;break}if(null!==s&&s>n){console.error("THREE.KeyframeTrack: Out of order keys.",this,e,n,s),t=!1;break}s=n}if(void 0!==n&&Yl(n))for(let e=0,i=n.length;e!==i;++e){const i=n[e];if(isNaN(i)){console.error("THREE.KeyframeTrack: Value is not a valid number.",this,e,i),t=!1;break}}return t}optimize(){const t=ql(this.times),e=ql(this.values),i=this.getValueSize(),n=this.getInterpolation()===tt,r=t.length-1;let s=1;for(let a=1;a0){t[s]=t[r];for(let t=r*i,n=s*i,a=0;a!==i;++a)e[n+a]=e[t+a];++s}return s!==t.length?(this.times=ql(t,0,s),this.values=ql(e,0,s*i)):(this.times=t,this.values=e),this}clone(){const t=ql(this.times,0),e=ql(this.values,0),i=new(0,this.constructor)(this.name,t,e);return i.createInterpolant=this.createInterpolant,i}}nc.prototype.TimeBufferType=Float32Array,nc.prototype.ValueBufferType=Float32Array,nc.prototype.DefaultInterpolation=Q;class rc extends nc{}rc.prototype.ValueTypeName="bool",rc.prototype.ValueBufferType=Array,rc.prototype.DefaultInterpolation=$,rc.prototype.InterpolantFactoryMethodLinear=void 0,rc.prototype.InterpolantFactoryMethodSmooth=void 0;class sc extends nc{}sc.prototype.ValueTypeName="color";class ac extends nc{}ac.prototype.ValueTypeName="number";class oc extends Ql{constructor(t,e,i,n){super(t,e,i,n)}interpolate_(t,e,i,n){const r=this.resultBuffer,s=this.sampleValues,a=this.valueSize,o=(i-e)/(n-e);let l=t*a;for(let t=l+a;l!==t;l+=4)ne.slerpFlat(r,0,s,l-a,s,l,o);return r}}class lc extends nc{InterpolantFactoryMethodLinear(t){return new oc(this.times,this.values,this.getValueSize(),t)}}lc.prototype.ValueTypeName="quaternion",lc.prototype.DefaultInterpolation=Q,lc.prototype.InterpolantFactoryMethodSmooth=void 0;class cc extends nc{}cc.prototype.ValueTypeName="string",cc.prototype.ValueBufferType=Array,cc.prototype.DefaultInterpolation=$,cc.prototype.InterpolantFactoryMethodLinear=void 0,cc.prototype.InterpolantFactoryMethodSmooth=void 0;class hc extends nc{}hc.prototype.ValueTypeName="vector";class uc{constructor(t,e=-1,i,n=2500){this.name=t,this.tracks=i,this.duration=e,this.blendMode=n,this.uuid=_t(),this.duration<0&&this.resetDuration()}static parse(t){const e=[],i=t.tracks,n=1/(t.fps||1);for(let t=0,r=i.length;t!==r;++t)e.push(dc(i[t]).scale(n));const r=new this(t.name,t.duration,e,t.blendMode);return r.uuid=t.uuid,r}static toJSON(t){const e=[],i=t.tracks,n={name:t.name,duration:t.duration,tracks:e,uuid:t.uuid,blendMode:t.blendMode};for(let t=0,n=i.length;t!==n;++t)e.push(nc.toJSON(i[t]));return n}static CreateFromMorphTargetSequence(t,e,i,n){const r=e.length,s=[];for(let t=0;t1){const t=s[1];let e=n[t];e||(n[t]=e=[]),e.push(i)}}const s=[];for(const t in n)s.push(this.CreateFromMorphTargetSequence(t,n[t],e,i));return s}static parseAnimation(t,e){if(!t)return console.error("THREE.AnimationClip: No animation in JSONLoader data."),null;const i=function(t,e,i,n,r){if(0!==i.length){const s=[],a=[];Kl(i,s,a,n),0!==s.length&&r.push(new t(e,s,a))}},n=[],r=t.name||"default",s=t.fps||30,a=t.blendMode;let o=t.length||-1;const l=t.hierarchy||[];for(let t=0;t{e&&e(r),this.manager.itemEnd(t)}),0),r;if(void 0!==vc[t])return void vc[t].push({onLoad:e,onProgress:i,onError:n});vc[t]=[],vc[t].push({onLoad:e,onProgress:i,onError:n});const s=new Request(t,{headers:new Headers(this.requestHeader),credentials:this.withCredentials?"include":"same-origin"}),a=this.mimeType,o=this.responseType;fetch(s).then((e=>{if(200===e.status||0===e.status){if(0===e.status&&console.warn("THREE.FileLoader: HTTP Status 0 received."),"undefined"==typeof ReadableStream||void 0===e.body||void 0===e.body.getReader)return e;const i=vc[t],n=e.body.getReader(),r=e.headers.get("Content-Length")||e.headers.get("X-File-Size"),s=r?parseInt(r):0,a=0!==s;let o=0;const l=new ReadableStream({start(t){!function e(){n.read().then((({done:n,value:r})=>{if(n)t.close();else{o+=r.byteLength;const n=new ProgressEvent("progress",{lengthComputable:a,loaded:o,total:s});for(let t=0,e=i.length;t{switch(o){case"arraybuffer":return t.arrayBuffer();case"blob":return t.blob();case"document":return t.text().then((t=>(new DOMParser).parseFromString(t,a)));case"json":return t.json();default:if(void 0===a)return t.text();{const e=/charset="?([^;"\s]*)"?/i.exec(a),i=e&&e[1]?e[1].toLowerCase():void 0,n=new TextDecoder(i);return t.arrayBuffer().then((t=>n.decode(t)))}}})).then((e=>{pc.add(t,e);const i=vc[t];delete vc[t];for(let t=0,n=i.length;t{const i=vc[t];if(void 0===i)throw this.manager.itemError(t),e;delete vc[t];for(let t=0,n=i.length;t{this.manager.itemEnd(t)})),this.manager.itemStart(t)}setResponseType(t){return this.responseType=t,this}setMimeType(t){return this.mimeType=t,this}}class yc extends gc{constructor(t){super(t)}load(t,e,i,n){void 0!==this.path&&(t=this.path+t),t=this.manager.resolveURL(t);const r=this,s=pc.get(t);if(void 0!==s)return r.manager.itemStart(t),setTimeout((function(){e&&e(s),r.manager.itemEnd(t)}),0),s;const a=Ot("img");function o(){c(),pc.add(t,this),e&&e(this),r.manager.itemEnd(t)}function l(e){c(),n&&n(e),r.manager.itemError(t),r.manager.itemEnd(t)}function c(){a.removeEventListener("load",o,!1),a.removeEventListener("error",l,!1)}return a.addEventListener("load",o,!1),a.addEventListener("error",l,!1),"data:"!==t.slice(0,5)&&void 0!==this.crossOrigin&&(a.crossOrigin=this.crossOrigin),r.manager.itemStart(t),a.src=t,a}}class Mc extends si{constructor(t,e=1){super(),this.isLight=!0,this.type="Light",this.color=new qt(t),this.intensity=e}dispose(){}copy(t,e){return super.copy(t,e),this.color.copy(t.color),this.intensity=t.intensity,this}toJSON(t){const e=super.toJSON(t);return e.object.color=this.color.getHex(),e.object.intensity=this.intensity,void 0!==this.groundColor&&(e.object.groundColor=this.groundColor.getHex()),void 0!==this.distance&&(e.object.distance=this.distance),void 0!==this.angle&&(e.object.angle=this.angle),void 0!==this.decay&&(e.object.decay=this.decay),void 0!==this.penumbra&&(e.object.penumbra=this.penumbra),void 0!==this.shadow&&(e.object.shadow=this.shadow.toJSON()),e}}class bc extends Mc{constructor(t,e,i){super(t,i),this.isHemisphereLight=!0,this.type="HemisphereLight",this.position.copy(si.DefaultUp),this.updateMatrix(),this.groundColor=new qt(e)}copy(t,e){return super.copy(t,e),this.groundColor.copy(t.groundColor),this}}const wc=new Ne,Sc=new re,Tc=new re;class Ac{constructor(t){this.camera=t,this.bias=0,this.normalBias=0,this.radius=1,this.blurSamples=8,this.mapSize=new Lt(512,512),this.map=null,this.mapPass=null,this.matrix=new Ne,this.autoUpdate=!0,this.needsUpdate=!1,this._frustum=new xn,this._frameExtents=new Lt(1,1),this._viewportCount=1,this._viewports=[new Qt(0,0,1,1)]}getViewportCount(){return this._viewportCount}getFrustum(){return this._frustum}updateMatrices(t){const e=this.camera,i=this.matrix;Sc.setFromMatrixPosition(t.matrixWorld),e.position.copy(Sc),Tc.setFromMatrixPosition(t.target.matrixWorld),e.lookAt(Tc),e.updateMatrixWorld(),wc.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this._frustum.setFromProjectionMatrix(wc),i.set(.5,0,0,.5,0,.5,0,.5,0,0,.5,.5,0,0,0,1),i.multiply(wc)}getViewport(t){return this._viewports[t]}getFrameExtents(){return this._frameExtents}dispose(){this.map&&this.map.dispose(),this.mapPass&&this.mapPass.dispose()}copy(t){return this.camera=t.camera.clone(),this.bias=t.bias,this.radius=t.radius,this.mapSize.copy(t.mapSize),this}clone(){return(new this.constructor).copy(this)}toJSON(){const t={};return 0!==this.bias&&(t.bias=this.bias),0!==this.normalBias&&(t.normalBias=this.normalBias),1!==this.radius&&(t.radius=this.radius),512===this.mapSize.x&&512===this.mapSize.y||(t.mapSize=this.mapSize.toArray()),t.camera=this.camera.toJSON(!1).object,delete t.camera.matrix,t}}class Ec extends Ac{constructor(){super(new on(50,1,.5,500)),this.isSpotLightShadow=!0,this.focus=1}updateMatrices(t){const e=this.camera,i=2*xt*t.angle*this.focus,n=this.mapSize.width/this.mapSize.height,r=t.distance||e.far;i===e.fov&&n===e.aspect&&r===e.far||(e.fov=i,e.aspect=n,e.far=r,e.updateProjectionMatrix()),super.updateMatrices(t)}copy(t){return super.copy(t),this.focus=t.focus,this}}class Cc extends Mc{constructor(t,e,i=0,n=Math.PI/3,r=0,s=2){super(t,e),this.isSpotLight=!0,this.type="SpotLight",this.position.copy(si.DefaultUp),this.updateMatrix(),this.target=new si,this.distance=i,this.angle=n,this.penumbra=r,this.decay=s,this.map=null,this.shadow=new Ec}get power(){return this.intensity*Math.PI}set power(t){this.intensity=t/Math.PI}dispose(){this.shadow.dispose()}copy(t,e){return super.copy(t,e),this.distance=t.distance,this.angle=t.angle,this.penumbra=t.penumbra,this.decay=t.decay,this.target=t.target.clone(),this.shadow=t.shadow.clone(),this}}const Lc=new Ne,Rc=new re,Pc=new re;class Ic extends Ac{constructor(){super(new on(90,1,.5,500)),this.isPointLightShadow=!0,this._frameExtents=new Lt(4,2),this._viewportCount=6,this._viewports=[new Qt(2,1,1,1),new Qt(0,1,1,1),new Qt(3,1,1,1),new Qt(1,1,1,1),new Qt(3,0,1,1),new Qt(1,0,1,1)],this._cubeDirections=[new re(1,0,0),new re(-1,0,0),new re(0,0,1),new re(0,0,-1),new re(0,1,0),new re(0,-1,0)],this._cubeUps=[new re(0,1,0),new re(0,1,0),new re(0,1,0),new re(0,1,0),new re(0,0,1),new re(0,0,-1)]}updateMatrices(t,e=0){const i=this.camera,n=this.matrix,r=t.distance||i.far;r!==i.far&&(i.far=r,i.updateProjectionMatrix()),Rc.setFromMatrixPosition(t.matrixWorld),i.position.copy(Rc),Pc.copy(i.position),Pc.add(this._cubeDirections[e]),i.up.copy(this._cubeUps[e]),i.lookAt(Pc),i.updateMatrixWorld(),n.makeTranslation(-Rc.x,-Rc.y,-Rc.z),Lc.multiplyMatrices(i.projectionMatrix,i.matrixWorldInverse),this._frustum.setFromProjectionMatrix(Lc)}}class Dc extends Mc{constructor(t,e,i=0,n=2){super(t,e),this.isPointLight=!0,this.type="PointLight",this.distance=i,this.decay=n,this.shadow=new Ic}get power(){return 4*this.intensity*Math.PI}set power(t){this.intensity=t/(4*Math.PI)}dispose(){this.shadow.dispose()}copy(t,e){return super.copy(t,e),this.distance=t.distance,this.decay=t.decay,this.shadow=t.shadow.clone(),this}}class Nc extends Ac{constructor(){super(new In(-5,5,5,-5,.5,500)),this.isDirectionalLightShadow=!0}}class Oc extends Mc{constructor(t,e){super(t,e),this.isDirectionalLight=!0,this.type="DirectionalLight",this.position.copy(si.DefaultUp),this.updateMatrix(),this.target=new si,this.shadow=new Nc}dispose(){this.shadow.dispose()}copy(t){return super.copy(t),this.target=t.target.clone(),this.shadow=t.shadow.clone(),this}}class zc extends Mc{constructor(t,e){super(t,e),this.isAmbientLight=!0,this.type="AmbientLight"}}class Uc extends Mc{constructor(t,e,i=10,n=10){super(t,e),this.isRectAreaLight=!0,this.type="RectAreaLight",this.width=i,this.height=n}get power(){return this.intensity*this.width*this.height*Math.PI}set power(t){this.intensity=t/(this.width*this.height*Math.PI)}copy(t){return super.copy(t),this.width=t.width,this.height=t.height,this}toJSON(t){const e=super.toJSON(t);return e.object.width=this.width,e.object.height=this.height,e}}class Bc{constructor(){this.isSphericalHarmonics3=!0,this.coefficients=[];for(let t=0;t<9;t++)this.coefficients.push(new re)}set(t){for(let e=0;e<9;e++)this.coefficients[e].copy(t[e]);return this}zero(){for(let t=0;t<9;t++)this.coefficients[t].set(0,0,0);return this}getAt(t,e){const i=t.x,n=t.y,r=t.z,s=this.coefficients;return e.copy(s[0]).multiplyScalar(.282095),e.addScaledVector(s[1],.488603*n),e.addScaledVector(s[2],.488603*r),e.addScaledVector(s[3],.488603*i),e.addScaledVector(s[4],i*n*1.092548),e.addScaledVector(s[5],n*r*1.092548),e.addScaledVector(s[6],.315392*(3*r*r-1)),e.addScaledVector(s[7],i*r*1.092548),e.addScaledVector(s[8],.546274*(i*i-n*n)),e}getIrradianceAt(t,e){const i=t.x,n=t.y,r=t.z,s=this.coefficients;return e.copy(s[0]).multiplyScalar(.886227),e.addScaledVector(s[1],1.023328*n),e.addScaledVector(s[2],1.023328*r),e.addScaledVector(s[3],1.023328*i),e.addScaledVector(s[4],.858086*i*n),e.addScaledVector(s[5],.858086*n*r),e.addScaledVector(s[6],.743125*r*r-.247708),e.addScaledVector(s[7],.858086*i*r),e.addScaledVector(s[8],.429043*(i*i-n*n)),e}add(t){for(let e=0;e<9;e++)this.coefficients[e].add(t.coefficients[e]);return this}addScaledSH(t,e){for(let i=0;i<9;i++)this.coefficients[i].addScaledVector(t.coefficients[i],e);return this}scale(t){for(let e=0;e<9;e++)this.coefficients[e].multiplyScalar(t);return this}lerp(t,e){for(let i=0;i<9;i++)this.coefficients[i].lerp(t.coefficients[i],e);return this}equals(t){for(let e=0;e<9;e++)if(!this.coefficients[e].equals(t.coefficients[e]))return!1;return!0}copy(t){return this.set(t.coefficients)}clone(){return(new this.constructor).copy(this)}fromArray(t,e=0){const i=this.coefficients;for(let n=0;n<9;n++)i[n].fromArray(t,e+3*n);return this}toArray(t=[],e=0){const i=this.coefficients;for(let n=0;n<9;n++)i[n].toArray(t,e+3*n);return t}static getBasisAt(t,e){const i=t.x,n=t.y,r=t.z;e[0]=.282095,e[1]=.488603*n,e[2]=.488603*r,e[3]=.488603*i,e[4]=1.092548*i*n,e[5]=1.092548*n*r,e[6]=.315392*(3*r*r-1),e[7]=1.092548*i*r,e[8]=.546274*(i*i-n*n)}}class Fc extends Mc{constructor(t=new Bc,e=1){super(void 0,e),this.isLightProbe=!0,this.sh=t}copy(t){return super.copy(t),this.sh.copy(t.sh),this}fromJSON(t){return this.intensity=t.intensity,this.sh.fromArray(t.sh),this}toJSON(t){const e=super.toJSON(t);return e.object.sh=this.sh.toArray(),e}}class kc extends gc{constructor(t){super(t),this.textures={}}load(t,e,i,n){const r=this,s=new _c(r.manager);s.setPath(r.path),s.setRequestHeader(r.requestHeader),s.setWithCredentials(r.withCredentials),s.load(t,(function(i){try{e(r.parse(JSON.parse(i)))}catch(e){n?n(e):console.error(e),r.manager.itemError(t)}}),i,n)}parse(t){const e=this.textures;function i(t){return void 0===e[t]&&console.warn("THREE.MaterialLoader: Undefined texture",t),e[t]}const n=kc.createMaterialFromType(t.type);if(void 0!==t.uuid&&(n.uuid=t.uuid),void 0!==t.name&&(n.name=t.name),void 0!==t.color&&void 0!==n.color&&n.color.setHex(t.color),void 0!==t.roughness&&(n.roughness=t.roughness),void 0!==t.metalness&&(n.metalness=t.metalness),void 0!==t.sheen&&(n.sheen=t.sheen),void 0!==t.sheenColor&&(n.sheenColor=(new qt).setHex(t.sheenColor)),void 0!==t.sheenRoughness&&(n.sheenRoughness=t.sheenRoughness),void 0!==t.emissive&&void 0!==n.emissive&&n.emissive.setHex(t.emissive),void 0!==t.specular&&void 0!==n.specular&&n.specular.setHex(t.specular),void 0!==t.specularIntensity&&(n.specularIntensity=t.specularIntensity),void 0!==t.specularColor&&void 0!==n.specularColor&&n.specularColor.setHex(t.specularColor),void 0!==t.shininess&&(n.shininess=t.shininess),void 0!==t.clearcoat&&(n.clearcoat=t.clearcoat),void 0!==t.clearcoatRoughness&&(n.clearcoatRoughness=t.clearcoatRoughness),void 0!==t.iridescence&&(n.iridescence=t.iridescence),void 0!==t.iridescenceIOR&&(n.iridescenceIOR=t.iridescenceIOR),void 0!==t.iridescenceThicknessRange&&(n.iridescenceThicknessRange=t.iridescenceThicknessRange),void 0!==t.transmission&&(n.transmission=t.transmission),void 0!==t.thickness&&(n.thickness=t.thickness),void 0!==t.attenuationDistance&&(n.attenuationDistance=t.attenuationDistance),void 0!==t.attenuationColor&&void 0!==n.attenuationColor&&n.attenuationColor.setHex(t.attenuationColor),void 0!==t.fog&&(n.fog=t.fog),void 0!==t.flatShading&&(n.flatShading=t.flatShading),void 0!==t.blending&&(n.blending=t.blending),void 0!==t.combine&&(n.combine=t.combine),void 0!==t.side&&(n.side=t.side),void 0!==t.shadowSide&&(n.shadowSide=t.shadowSide),void 0!==t.opacity&&(n.opacity=t.opacity),void 0!==t.transparent&&(n.transparent=t.transparent),void 0!==t.alphaTest&&(n.alphaTest=t.alphaTest),void 0!==t.depthTest&&(n.depthTest=t.depthTest),void 0!==t.depthWrite&&(n.depthWrite=t.depthWrite),void 0!==t.colorWrite&&(n.colorWrite=t.colorWrite),void 0!==t.stencilWrite&&(n.stencilWrite=t.stencilWrite),void 0!==t.stencilWriteMask&&(n.stencilWriteMask=t.stencilWriteMask),void 0!==t.stencilFunc&&(n.stencilFunc=t.stencilFunc),void 0!==t.stencilRef&&(n.stencilRef=t.stencilRef),void 0!==t.stencilFuncMask&&(n.stencilFuncMask=t.stencilFuncMask),void 0!==t.stencilFail&&(n.stencilFail=t.stencilFail),void 0!==t.stencilZFail&&(n.stencilZFail=t.stencilZFail),void 0!==t.stencilZPass&&(n.stencilZPass=t.stencilZPass),void 0!==t.wireframe&&(n.wireframe=t.wireframe),void 0!==t.wireframeLinewidth&&(n.wireframeLinewidth=t.wireframeLinewidth),void 0!==t.wireframeLinecap&&(n.wireframeLinecap=t.wireframeLinecap),void 0!==t.wireframeLinejoin&&(n.wireframeLinejoin=t.wireframeLinejoin),void 0!==t.rotation&&(n.rotation=t.rotation),1!==t.linewidth&&(n.linewidth=t.linewidth),void 0!==t.dashSize&&(n.dashSize=t.dashSize),void 0!==t.gapSize&&(n.gapSize=t.gapSize),void 0!==t.scale&&(n.scale=t.scale),void 0!==t.polygonOffset&&(n.polygonOffset=t.polygonOffset),void 0!==t.polygonOffsetFactor&&(n.polygonOffsetFactor=t.polygonOffsetFactor),void 0!==t.polygonOffsetUnits&&(n.polygonOffsetUnits=t.polygonOffsetUnits),void 0!==t.dithering&&(n.dithering=t.dithering),void 0!==t.alphaToCoverage&&(n.alphaToCoverage=t.alphaToCoverage),void 0!==t.premultipliedAlpha&&(n.premultipliedAlpha=t.premultipliedAlpha),void 0!==t.visible&&(n.visible=t.visible),void 0!==t.toneMapped&&(n.toneMapped=t.toneMapped),void 0!==t.userData&&(n.userData=t.userData),void 0!==t.vertexColors&&("number"==typeof t.vertexColors?n.vertexColors=t.vertexColors>0:n.vertexColors=t.vertexColors),void 0!==t.uniforms)for(const e in t.uniforms){const r=t.uniforms[e];switch(n.uniforms[e]={},r.type){case"t":n.uniforms[e].value=i(r.value);break;case"c":n.uniforms[e].value=(new qt).setHex(r.value);break;case"v2":n.uniforms[e].value=(new Lt).fromArray(r.value);break;case"v3":n.uniforms[e].value=(new re).fromArray(r.value);break;case"v4":n.uniforms[e].value=(new Qt).fromArray(r.value);break;case"m3":n.uniforms[e].value=(new Rt).fromArray(r.value);break;case"m4":n.uniforms[e].value=(new Ne).fromArray(r.value);break;default:n.uniforms[e].value=r.value}}if(void 0!==t.defines&&(n.defines=t.defines),void 0!==t.vertexShader&&(n.vertexShader=t.vertexShader),void 0!==t.fragmentShader&&(n.fragmentShader=t.fragmentShader),void 0!==t.glslVersion&&(n.glslVersion=t.glslVersion),void 0!==t.extensions)for(const e in t.extensions)n.extensions[e]=t.extensions[e];if(void 0!==t.size&&(n.size=t.size),void 0!==t.sizeAttenuation&&(n.sizeAttenuation=t.sizeAttenuation),void 0!==t.map&&(n.map=i(t.map)),void 0!==t.matcap&&(n.matcap=i(t.matcap)),void 0!==t.alphaMap&&(n.alphaMap=i(t.alphaMap)),void 0!==t.bumpMap&&(n.bumpMap=i(t.bumpMap)),void 0!==t.bumpScale&&(n.bumpScale=t.bumpScale),void 0!==t.normalMap&&(n.normalMap=i(t.normalMap)),void 0!==t.normalMapType&&(n.normalMapType=t.normalMapType),void 0!==t.normalScale){let e=t.normalScale;!1===Array.isArray(e)&&(e=[e,e]),n.normalScale=(new Lt).fromArray(e)}return void 0!==t.displacementMap&&(n.displacementMap=i(t.displacementMap)),void 0!==t.displacementScale&&(n.displacementScale=t.displacementScale),void 0!==t.displacementBias&&(n.displacementBias=t.displacementBias),void 0!==t.roughnessMap&&(n.roughnessMap=i(t.roughnessMap)),void 0!==t.metalnessMap&&(n.metalnessMap=i(t.metalnessMap)),void 0!==t.emissiveMap&&(n.emissiveMap=i(t.emissiveMap)),void 0!==t.emissiveIntensity&&(n.emissiveIntensity=t.emissiveIntensity),void 0!==t.specularMap&&(n.specularMap=i(t.specularMap)),void 0!==t.specularIntensityMap&&(n.specularIntensityMap=i(t.specularIntensityMap)),void 0!==t.specularColorMap&&(n.specularColorMap=i(t.specularColorMap)),void 0!==t.envMap&&(n.envMap=i(t.envMap)),void 0!==t.envMapIntensity&&(n.envMapIntensity=t.envMapIntensity),void 0!==t.reflectivity&&(n.reflectivity=t.reflectivity),void 0!==t.refractionRatio&&(n.refractionRatio=t.refractionRatio),void 0!==t.lightMap&&(n.lightMap=i(t.lightMap)),void 0!==t.lightMapIntensity&&(n.lightMapIntensity=t.lightMapIntensity),void 0!==t.aoMap&&(n.aoMap=i(t.aoMap)),void 0!==t.aoMapIntensity&&(n.aoMapIntensity=t.aoMapIntensity),void 0!==t.gradientMap&&(n.gradientMap=i(t.gradientMap)),void 0!==t.clearcoatMap&&(n.clearcoatMap=i(t.clearcoatMap)),void 0!==t.clearcoatRoughnessMap&&(n.clearcoatRoughnessMap=i(t.clearcoatRoughnessMap)),void 0!==t.clearcoatNormalMap&&(n.clearcoatNormalMap=i(t.clearcoatNormalMap)),void 0!==t.clearcoatNormalScale&&(n.clearcoatNormalScale=(new Lt).fromArray(t.clearcoatNormalScale)),void 0!==t.iridescenceMap&&(n.iridescenceMap=i(t.iridescenceMap)),void 0!==t.iridescenceThicknessMap&&(n.iridescenceThicknessMap=i(t.iridescenceThicknessMap)),void 0!==t.transmissionMap&&(n.transmissionMap=i(t.transmissionMap)),void 0!==t.thicknessMap&&(n.thicknessMap=i(t.thicknessMap)),void 0!==t.sheenColorMap&&(n.sheenColorMap=i(t.sheenColorMap)),void 0!==t.sheenRoughnessMap&&(n.sheenRoughnessMap=i(t.sheenRoughnessMap)),n}setTextures(t){return this.textures=t,this}static createMaterialFromType(t){return new{ShadowMaterial:zl,SpriteMaterial:ha,RawShaderMaterial:Ul,ShaderMaterial:sn,PointsMaterial:ro,MeshPhysicalMaterial:Fl,MeshStandardMaterial:Bl,MeshPhongMaterial:kl,MeshToonMaterial:Gl,MeshNormalMaterial:Vl,MeshLambertMaterial:Hl,MeshDepthMaterial:Us,MeshDistanceMaterial:Bs,MeshBasicMaterial:_i,MeshMatcapMaterial:Wl,LineDashedMaterial:jl,LineBasicMaterial:Xa,Material:xi}[t]}}class Gc{static decodeText(t){if("undefined"!=typeof TextDecoder)return(new TextDecoder).decode(t);let e="";for(let i=0,n=t.length;i0){this.source.connect(this.filters[0]);for(let t=1,e=this.filters.length;t0){this.source.disconnect(this.filters[0]);for(let t=1,e=this.filters.length;t0&&this._mixBufferRegionAdditive(i,n,this._addIndex*e,1,e);for(let t=e,r=e+e;t!==r;++t)if(i[t]!==i[t+e]){a.setValue(i,n);break}}saveOriginalState(){const t=this.binding,e=this.buffer,i=this.valueSize,n=i*this._origIndex;t.getValue(e,n);for(let t=i,r=n;t!==r;++t)e[t]=e[n+t%i];this._setIdentity(),this.cumulativeWeight=0,this.cumulativeWeightAdditive=0}restoreOriginalState(){const t=3*this.valueSize;this.binding.setValue(this.buffer,t)}_setAdditiveIdentityNumeric(){const t=this._addIndex*this.valueSize,e=t+this.valueSize;for(let i=t;i=.5)for(let n=0;n!==r;++n)t[e+n]=t[i+n]}_slerp(t,e,i,n){ne.slerpFlat(t,e,t,e,t,i,n)}_slerpAdditive(t,e,i,n,r){const s=this._workIndex*r;ne.multiplyQuaternionsFlat(t,s,t,e,t,i),ne.slerpFlat(t,e,t,e,t,s,n)}_lerp(t,e,i,n,r){const s=1-n;for(let a=0;a!==r;++a){const r=e+a;t[r]=t[r]*s+t[i+a]*n}}_lerpAdditive(t,e,i,n,r){for(let s=0;s!==r;++s){const r=e+s;t[r]=t[r]+t[i+s]*n}}}const hh="\\[\\]\\.:\\/",uh=new RegExp("[\\[\\]\\.:\\/]","g"),dh="[^\\[\\]\\.:\\/]",ph="[^"+hh.replace("\\.","")+"]",mh=new RegExp("^"+/((?:WC+[\/:])*)/.source.replace("WC",dh)+/(WCOD+)?/.source.replace("WCOD",ph)+/(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace("WC",dh)+/\.(WC+)(?:\[(.+)\])?/.source.replace("WC",dh)+"$"),fh=["material","materials","bones","map"];class gh{constructor(t,e,i){this.path=e,this.parsedPath=i||gh.parseTrackName(e),this.node=gh.findNode(t,this.parsedPath.nodeName)||t,this.rootNode=t,this.getValue=this._getValue_unbound,this.setValue=this._setValue_unbound}static create(t,e,i){return t&&t.isAnimationObjectGroup?new gh.Composite(t,e,i):new gh(t,e,i)}static sanitizeNodeName(t){return t.replace(/\s/g,"_").replace(uh,"")}static parseTrackName(t){const e=mh.exec(t);if(null===e)throw new Error("PropertyBinding: Cannot parse trackName: "+t);const i={nodeName:e[2],objectName:e[3],objectIndex:e[4],propertyName:e[5],propertyIndex:e[6]},n=i.nodeName&&i.nodeName.lastIndexOf(".");if(void 0!==n&&-1!==n){const t=i.nodeName.substring(n+1);-1!==fh.indexOf(t)&&(i.nodeName=i.nodeName.substring(0,n),i.objectName=t)}if(null===i.propertyName||0===i.propertyName.length)throw new Error("PropertyBinding: can not parse propertyName from trackName: "+t);return i}static findNode(t,e){if(void 0===e||""===e||"."===e||-1===e||e===t.name||e===t.uuid)return t;if(t.skeleton){const i=t.skeleton.getBoneByName(e);if(void 0!==i)return i}if(t.children){const i=function(t){for(let n=0;n0){const t=this._interpolants,e=this._propertyBindings;if(this.blendMode===st)for(let i=0,n=t.length;i!==n;++i)t[i].evaluate(s),e[i].accumulateAdditive(a);else for(let i=0,r=t.length;i!==r;++i)t[i].evaluate(s),e[i].accumulate(n,a)}}_updateWeight(t){let e=0;if(this.enabled){e=this.weight;const i=this._weightInterpolant;if(null!==i){const n=i.evaluate(t)[0];e*=n,t>i.parameterPositions[1]&&(this.stopFading(),0===n&&(this.enabled=!1))}}return this._effectiveWeight=e,e}_updateTimeScale(t){let e=0;if(!this.paused){e=this.timeScale;const i=this._timeScaleInterpolant;if(null!==i){e*=i.evaluate(t)[0],t>i.parameterPositions[1]&&(this.stopWarping(),0===e?this.paused=!0:this.timeScale=e)}}return this._effectiveTimeScale=e,e}_updateTime(t){const e=this._clip.duration,i=this.loop;let n=this.time+t,r=this._loopCount;const s=2202===i;if(0===t)return-1===r?n:s&&1==(1&r)?e-n:n;if(2200===i){-1===r&&(this._loopCount=0,this._setEndings(!0,!0,!1));t:{if(n>=e)n=e;else{if(!(n<0)){this.time=n;break t}n=0}this.clampWhenFinished?this.paused=!0:this.enabled=!1,this.time=n,this._mixer.dispatchEvent({type:"finished",action:this,direction:t<0?-1:1})}}else{if(-1===r&&(t>=0?(r=0,this._setEndings(!0,0===this.repetitions,s)):this._setEndings(0===this.repetitions,!0,s)),n>=e||n<0){const i=Math.floor(n/e);n-=e*i,r+=Math.abs(i);const a=this.repetitions-r;if(a<=0)this.clampWhenFinished?this.paused=!0:this.enabled=!1,n=t>0?e:0,this.time=n,this._mixer.dispatchEvent({type:"finished",action:this,direction:t>0?1:-1});else{if(1===a){const e=t<0;this._setEndings(e,!e,s)}else this._setEndings(!1,!1,s);this._loopCount=r,this.time=n,this._mixer.dispatchEvent({type:"loop",action:this,loopDelta:i})}}else this.time=n;if(s&&1==(1&r))return e-n}return n}_setEndings(t,e,i){const n=this._interpolantSettings;i?(n.endingStart=it,n.endingEnd=it):(n.endingStart=t?this.zeroSlopeAtStart?it:et:nt,n.endingEnd=e?this.zeroSlopeAtEnd?it:et:nt)}_scheduleFading(t,e,i){const n=this._mixer,r=n.time;let s=this._weightInterpolant;null===s&&(s=n._lendControlInterpolant(),this._weightInterpolant=s);const a=s.parameterPositions,o=s.sampleValues;return a[0]=r,o[0]=e,a[1]=r+t,o[1]=i,this}}const xh=new Float32Array(1);class _h{constructor(t){this.value=t}clone(){return new _h(void 0===this.value.clone?this.value:this.value.clone())}}let yh=0;function Mh(t,e){return t.distance-e.distance}function bh(t,e,i,n){if(t.layers.test(e.layers)&&t.raycast(e,i),!0===n){const n=t.children;for(let t=0,r=n.length;t>-e-14,n[256|t]=1024>>-e-14|32768,r[t]=-e-1,r[256|t]=-e-1):e<=15?(n[t]=e+15<<10,n[256|t]=e+15<<10|32768,r[t]=13,r[256|t]=13):e<128?(n[t]=31744,n[256|t]=64512,r[t]=24,r[256|t]=24):(n[t]=31744,n[256|t]=64512,r[t]=13,r[256|t]=13)}const s=new Uint32Array(2048),a=new Uint32Array(64),o=new Uint32Array(64);for(let t=1;t<1024;++t){let e=t<<13,i=0;for(;0==(8388608&e);)e<<=1,i-=8388608;e&=-8388609,i+=947912704,s[t]=e|i}for(let t=1024;t<2048;++t)s[t]=939524096+(t-1024<<13);for(let t=1;t<31;++t)a[t]=t<<23;a[31]=1199570944,a[32]=2147483648;for(let t=33;t<63;++t)a[t]=2147483648+(t-32<<23);a[63]=3347054592;for(let t=1;t<64;++t)32!==t&&(o[t]=1024);return{floatView:e,uint32View:i,baseTable:n,shiftTable:r,mantissaTable:s,exponentTable:a,offsetTable:o}}var qh=Object.freeze({__proto__:null,toHalfFloat:function(t){Math.abs(t)>65504&&console.warn("THREE.DataUtils.toHalfFloat(): Value out of range."),t=yt(t,-65504,65504),Wh.floatView[0]=t;const e=Wh.uint32View[0],i=e>>23&511;return Wh.baseTable[i]+((8388607&e)>>Wh.shiftTable[i])},fromHalfFloat:function(t){const e=t>>10;return Wh.uint32View[0]=Wh.mantissaTable[Wh.offsetTable[e]+(1023&t)]+Wh.exponentTable[e],Wh.floatView[0]}});"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("register",{detail:{revision:e}})),"undefined"!=typeof window&&(window.__THREE__?console.warn("WARNING: Multiple instances of Three.js being imported."):window.__THREE__=e),t.ACESFilmicToneMapping=4,t.AddEquation=i,t.AddOperation=2,t.AdditiveAnimationBlendMode=st,t.AdditiveBlending=2,t.AlphaFormat=1021,t.AlwaysDepth=1,t.AlwaysStencilFunc=519,t.AmbientLight=zc,t.AmbientLightProbe=class extends Fc{constructor(t,e=1){super(void 0,e),this.isAmbientLightProbe=!0;const i=(new qt).set(t);this.sh.coefficients[0].set(i.r,i.g,i.b).multiplyScalar(2*Math.sqrt(Math.PI))}},t.AnimationClip=uc,t.AnimationLoader=class extends gc{constructor(t){super(t)}load(t,e,i,n){const r=this,s=new _c(this.manager);s.setPath(this.path),s.setRequestHeader(this.requestHeader),s.setWithCredentials(this.withCredentials),s.load(t,(function(i){try{e(r.parse(JSON.parse(i)))}catch(e){n?n(e):console.error(e),r.manager.itemError(t)}}),i,n)}parse(t){const e=[];for(let i=0;i=0;--e)t[e].stop();return this}update(t){t*=this.timeScale;const e=this._actions,i=this._nActiveActions,n=this.time+=t,r=Math.sign(t),s=this._accuIndex^=1;for(let a=0;a!==i;++a){e[a]._update(n,t,r,s)}const a=this._bindings,o=this._nActiveBindings;for(let t=0;t!==o;++t)a[t].apply(s);return this}setTime(t){this.time=0;for(let t=0;t=r){const s=r++,c=t[s];e[c.uuid]=l,t[l]=c,e[o]=s,t[s]=a;for(let t=0,e=n;t!==e;++t){const e=i[t],n=e[s],r=e[l];e[l]=n,e[s]=r}}}this.nCachedObjects_=r}uncache(){const t=this._objects,e=this._indicesByUUID,i=this._bindings,n=i.length;let r=this.nCachedObjects_,s=t.length;for(let a=0,o=arguments.length;a!==o;++a){const o=arguments[a].uuid,l=e[o];if(void 0!==l)if(delete e[o],l0&&(e[a.uuid]=l),t[l]=a,t.pop();for(let t=0,e=n;t!==e;++t){const e=i[t];e[l]=e[r],e.pop()}}}this.nCachedObjects_=r}subscribe_(t,e){const i=this._bindingsIndicesByPath;let n=i[t];const r=this._bindings;if(void 0!==n)return r[n];const s=this._paths,a=this._parsedPaths,o=this._objects,l=o.length,c=this.nCachedObjects_,h=new Array(l);n=r.length,i[t]=n,s.push(t),a.push(e),r.push(h);for(let i=c,n=o.length;i!==n;++i){const n=o[i];h[i]=new gh(n,t,e)}return h}unsubscribe_(t){const e=this._bindingsIndicesByPath,i=e[t];if(void 0!==i){const n=this._paths,r=this._parsedPaths,s=this._bindings,a=s.length-1,o=s[a];e[t[a]]=i,s[i]=o,s.pop(),r[i]=r[a],r.pop(),n[i]=n[a],n.pop()}}},t.AnimationUtils=$l,t.ArcCurve=fo,t.ArrayCamera=js,t.ArrowHelper=class extends si{constructor(t=new re(0,0,1),e=new re(0,0,0),i=1,n=16776960,r=.2*i,s=.2*r){super(),this.type="ArrowHelper",void 0===Vh&&(Vh=new Di,Vh.setAttribute("position",new Ti([0,0,0,0,1,0],3)),Hh=new Bo(0,.5,1,5,1),Hh.translate(0,-.5,0)),this.position.copy(e),this.line=new Qa(Vh,new Xa({color:n,toneMapped:!1})),this.line.matrixAutoUpdate=!1,this.add(this.line),this.cone=new Ki(Hh,new _i({color:n,toneMapped:!1})),this.cone.matrixAutoUpdate=!1,this.add(this.cone),this.setDirection(t),this.setLength(i,r,s)}setDirection(t){if(t.y>.99999)this.quaternion.set(0,0,0,1);else if(t.y<-.99999)this.quaternion.set(1,0,0,0);else{Gh.set(t.z,0,-t.x).normalize();const e=Math.acos(t.y);this.quaternion.setFromAxisAngle(Gh,e)}}setLength(t,e=.2*t,i=.2*e){this.line.scale.set(1,Math.max(1e-4,t-e),1),this.line.updateMatrix(),this.cone.scale.set(i,e,i),this.cone.position.y=t,this.cone.updateMatrix()}setColor(t){this.line.material.color.set(t),this.cone.material.color.set(t)}copy(t){return super.copy(t,!1),this.line.copy(t.line),this.cone.copy(t.cone),this}dispose(){this.line.geometry.dispose(),this.line.material.dispose(),this.cone.geometry.dispose(),this.cone.material.dispose()}},t.Audio=rh,t.AudioAnalyser=class{constructor(t,e=2048){this.analyser=t.context.createAnalyser(),this.analyser.fftSize=e,this.data=new Uint8Array(this.analyser.frequencyBinCount),t.getOutput().connect(this.analyser)}getFrequencyData(){return this.analyser.getByteFrequencyData(this.data),this.data}getAverageFrequency(){let t=0;const e=this.getFrequencyData();for(let i=0;ithis.max.x||t.ythis.max.y)}containsBox(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y}getParameter(t,e){return e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y))}intersectsBox(t){return!(t.max.xthis.max.x||t.max.ythis.max.y)}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return wh.copy(t).clamp(this.min,this.max).sub(t).length()}intersect(t){return this.min.max(t.min),this.max.min(t.max),this}union(t){return this.min.min(t.min),this.max.max(t.max),this}translate(t){return this.min.add(t),this.max.add(t),this}equals(t){return t.min.equals(this.min)&&t.max.equals(this.max)}},t.Box3=oe,t.Box3Helper=class extends io{constructor(t,e=16776960){const i=new Uint16Array([0,1,1,2,2,3,3,0,4,5,5,6,6,7,7,4,0,4,1,5,2,6,3,7]),n=new Di;n.setIndex(new bi(i,1)),n.setAttribute("position",new Ti([1,1,1,-1,1,1,-1,-1,1,1,-1,1,1,1,-1,-1,1,-1,-1,-1,-1,1,-1,-1],3)),super(n,new Xa({color:e,toneMapped:!1})),this.box=t,this.type="Box3Helper",this.geometry.computeBoundingSphere()}updateMatrixWorld(t){const e=this.box;e.isEmpty()||(e.getCenter(this.position),e.getSize(this.scale),this.scale.multiplyScalar(.5),super.updateMatrixWorld(t))}dispose(){this.geometry.dispose(),this.material.dispose()}},t.BoxBufferGeometry=class extends Qi{constructor(t,e,i,n,r,s){console.warn("THREE.BoxBufferGeometry has been renamed to THREE.BoxGeometry."),super(t,e,i,n,r,s)}},t.BoxGeometry=Qi,t.BoxHelper=class extends io{constructor(t,e=16776960){const i=new Uint16Array([0,1,1,2,2,3,3,0,4,5,5,6,6,7,7,4,0,4,1,5,2,6,3,7]),n=new Float32Array(24),r=new Di;r.setIndex(new bi(i,1)),r.setAttribute("position",new bi(n,3)),super(r,new Xa({color:e,toneMapped:!1})),this.object=t,this.type="BoxHelper",this.matrixAutoUpdate=!1,this.update()}update(t){if(void 0!==t&&console.warn("THREE.BoxHelper: .update() has no longer arguments."),void 0!==this.object&&kh.setFromObject(this.object),kh.isEmpty())return;const e=kh.min,i=kh.max,n=this.geometry.attributes.position,r=n.array;r[0]=i.x,r[1]=i.y,r[2]=i.z,r[3]=e.x,r[4]=i.y,r[5]=i.z,r[6]=e.x,r[7]=e.y,r[8]=i.z,r[9]=i.x,r[10]=e.y,r[11]=i.z,r[12]=i.x,r[13]=i.y,r[14]=e.z,r[15]=e.x,r[16]=i.y,r[17]=e.z,r[18]=e.x,r[19]=e.y,r[20]=e.z,r[21]=i.x,r[22]=e.y,r[23]=e.z,n.needsUpdate=!0,this.geometry.computeBoundingSphere()}setFromObject(t){return this.object=t,this.update(),this}copy(t,e){return super.copy(t,e),this.object=t.object,this}dispose(){this.geometry.dispose(),this.material.dispose()}},t.BufferAttribute=bi,t.BufferGeometry=Di,t.BufferGeometryLoader=Hc,t.ByteType=1010,t.Cache=pc,t.Camera=an,t.CameraHelper=class extends io{constructor(t){const e=new Di,i=new Xa({color:16777215,vertexColors:!0,toneMapped:!1}),n=[],r=[],s={};function a(t,e){o(t),o(e)}function o(t){n.push(0,0,0),r.push(0,0,0),void 0===s[t]&&(s[t]=[]),s[t].push(n.length/3-1)}a("n1","n2"),a("n2","n4"),a("n4","n3"),a("n3","n1"),a("f1","f2"),a("f2","f4"),a("f4","f3"),a("f3","f1"),a("n1","f1"),a("n2","f2"),a("n3","f3"),a("n4","f4"),a("p","n1"),a("p","n2"),a("p","n3"),a("p","n4"),a("u1","u2"),a("u2","u3"),a("u3","u1"),a("c","t"),a("p","c"),a("cn1","cn2"),a("cn3","cn4"),a("cf1","cf2"),a("cf3","cf4"),e.setAttribute("position",new Ti(n,3)),e.setAttribute("color",new Ti(r,3)),super(e,i),this.type="CameraHelper",this.camera=t,this.camera.updateProjectionMatrix&&this.camera.updateProjectionMatrix(),this.matrix=t.matrixWorld,this.matrixAutoUpdate=!1,this.pointMap=s,this.update();const l=new qt(16755200),c=new qt(16711680),h=new qt(43775),u=new qt(16777215),d=new qt(3355443);this.setColors(l,c,h,u,d)}setColors(t,e,i,n,r){const s=this.geometry.getAttribute("color");s.setXYZ(0,t.r,t.g,t.b),s.setXYZ(1,t.r,t.g,t.b),s.setXYZ(2,t.r,t.g,t.b),s.setXYZ(3,t.r,t.g,t.b),s.setXYZ(4,t.r,t.g,t.b),s.setXYZ(5,t.r,t.g,t.b),s.setXYZ(6,t.r,t.g,t.b),s.setXYZ(7,t.r,t.g,t.b),s.setXYZ(8,t.r,t.g,t.b),s.setXYZ(9,t.r,t.g,t.b),s.setXYZ(10,t.r,t.g,t.b),s.setXYZ(11,t.r,t.g,t.b),s.setXYZ(12,t.r,t.g,t.b),s.setXYZ(13,t.r,t.g,t.b),s.setXYZ(14,t.r,t.g,t.b),s.setXYZ(15,t.r,t.g,t.b),s.setXYZ(16,t.r,t.g,t.b),s.setXYZ(17,t.r,t.g,t.b),s.setXYZ(18,t.r,t.g,t.b),s.setXYZ(19,t.r,t.g,t.b),s.setXYZ(20,t.r,t.g,t.b),s.setXYZ(21,t.r,t.g,t.b),s.setXYZ(22,t.r,t.g,t.b),s.setXYZ(23,t.r,t.g,t.b),s.setXYZ(24,e.r,e.g,e.b),s.setXYZ(25,e.r,e.g,e.b),s.setXYZ(26,e.r,e.g,e.b),s.setXYZ(27,e.r,e.g,e.b),s.setXYZ(28,e.r,e.g,e.b),s.setXYZ(29,e.r,e.g,e.b),s.setXYZ(30,e.r,e.g,e.b),s.setXYZ(31,e.r,e.g,e.b),s.setXYZ(32,i.r,i.g,i.b),s.setXYZ(33,i.r,i.g,i.b),s.setXYZ(34,i.r,i.g,i.b),s.setXYZ(35,i.r,i.g,i.b),s.setXYZ(36,i.r,i.g,i.b),s.setXYZ(37,i.r,i.g,i.b),s.setXYZ(38,n.r,n.g,n.b),s.setXYZ(39,n.r,n.g,n.b),s.setXYZ(40,r.r,r.g,r.b),s.setXYZ(41,r.r,r.g,r.b),s.setXYZ(42,r.r,r.g,r.b),s.setXYZ(43,r.r,r.g,r.b),s.setXYZ(44,r.r,r.g,r.b),s.setXYZ(45,r.r,r.g,r.b),s.setXYZ(46,r.r,r.g,r.b),s.setXYZ(47,r.r,r.g,r.b),s.setXYZ(48,r.r,r.g,r.b),s.setXYZ(49,r.r,r.g,r.b),s.needsUpdate=!0}update(){const t=this.geometry,e=this.pointMap;Bh.projectionMatrixInverse.copy(this.camera.projectionMatrixInverse),Fh("c",e,t,Bh,0,0,-1),Fh("t",e,t,Bh,0,0,1),Fh("n1",e,t,Bh,-1,-1,-1),Fh("n2",e,t,Bh,1,-1,-1),Fh("n3",e,t,Bh,-1,1,-1),Fh("n4",e,t,Bh,1,1,-1),Fh("f1",e,t,Bh,-1,-1,1),Fh("f2",e,t,Bh,1,-1,1),Fh("f3",e,t,Bh,-1,1,1),Fh("f4",e,t,Bh,1,1,1),Fh("u1",e,t,Bh,.7,1.1,-1),Fh("u2",e,t,Bh,-.7,1.1,-1),Fh("u3",e,t,Bh,0,2,-1),Fh("cf1",e,t,Bh,-1,0,1),Fh("cf2",e,t,Bh,1,0,1),Fh("cf3",e,t,Bh,0,-1,1),Fh("cf4",e,t,Bh,0,1,1),Fh("cn1",e,t,Bh,-1,0,-1),Fh("cn2",e,t,Bh,1,0,-1),Fh("cn3",e,t,Bh,0,-1,-1),Fh("cn4",e,t,Bh,0,1,-1),t.getAttribute("position").needsUpdate=!0}dispose(){this.geometry.dispose(),this.material.dispose()}},t.CanvasTexture=class extends $t{constructor(t,e,i,n,r,s,a,o,l){super(t,e,i,n,r,s,a,o,l),this.isCanvasTexture=!0,this.needsUpdate=!0}},t.CapsuleBufferGeometry=class extends zo{constructor(t,e,i,n){console.warn("THREE.CapsuleBufferGeometry has been renamed to THREE.CapsuleGeometry."),super(t,e,i,n)}},t.CapsuleGeometry=zo,t.CatmullRomCurve3=Mo,t.CineonToneMapping=3,t.CircleBufferGeometry=class extends Uo{constructor(t,e,i,n){console.warn("THREE.CircleBufferGeometry has been renamed to THREE.CircleGeometry."),super(t,e,i,n)}},t.CircleGeometry=Uo,t.ClampToEdgeWrapping=h,t.Clock=$c,t.Color=qt,t.ColorKeyframeTrack=sc,t.ColorManagement=Ft,t.CompressedArrayTexture=class extends uo{constructor(t,e,i,n,r,s){super(t,e,i,r,s),this.isCompressedArrayTexture=!0,this.image.depth=n,this.wrapR=h}},t.CompressedTexture=uo,t.CompressedTextureLoader=class extends gc{constructor(t){super(t)}load(t,e,i,n){const r=this,s=[],a=new uo,o=new _c(this.manager);o.setPath(this.path),o.setResponseType("arraybuffer"),o.setRequestHeader(this.requestHeader),o.setWithCredentials(r.withCredentials);let l=0;function c(c){o.load(t[c],(function(t){const i=r.parse(t,!0);s[c]={width:i.width,height:i.height,format:i.format,mipmaps:i.mipmaps},l+=1,6===l&&(1===i.mipmapCount&&(a.minFilter=f),a.image=s,a.format=i.format,a.needsUpdate=!0,e&&e(a))}),i,n)}if(Array.isArray(t))for(let e=0,i=t.length;e0){const i=new mc(e);r=new yc(i),r.setCrossOrigin(this.crossOrigin);for(let e=0,i=t.length;e0){n=new yc(this.manager),n.setCrossOrigin(this.crossOrigin);for(let e=0,n=t.length;e1)for(let i=0;iNumber.EPSILON){if(l<0&&(i=e[s],o=-o,a=e[r],l=-l),t.ya.y)continue;if(t.y===i.y){if(t.x===i.x)return!0}else{const e=l*(t.x-i.x)-o*(t.y-i.y);if(0===e)return!0;if(e<0)continue;n=!n}}else{if(t.y!==i.y)continue;if(a.x<=t.x&&t.x<=i.x||i.x<=t.x&&t.x<=a.x)return!0}}return n}const i=_l.isClockWise,n=this.subPaths;if(0===n.length)return[];let r,s,a;const o=[];if(1===n.length)return s=n[0],a=new Xo,a.curves=s.curves,o.push(a),o;let l=!i(n[0].getPoints());l=t?!l:l;const c=[],h=[];let u,d,p=[],m=0;h[m]=void 0,p[m]=[];for(let e=0,a=n.length;e1){let t=!1,i=0;for(let t=0,e=h.length;t0&&!1===t&&(p=c)}for(let t=0,e=h.length;t=t.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}},t.WebGL1Renderer=na,t.WebGL3DRenderTarget=class extends te{constructor(t=1,e=1,i=1){super(t,e),this.isWebGL3DRenderTarget=!0,this.depth=i,this.texture=new ie(null,t,e,i),this.texture.isRenderTargetTexture=!0}},t.WebGLArrayRenderTarget=class extends te{constructor(t=1,e=1,i=1){super(t,e),this.isWebGLArrayRenderTarget=!0,this.depth=i,this.texture=new ee(null,t,e,i),this.texture.isRenderTargetTexture=!0}},t.WebGLCubeRenderTarget=un,t.WebGLMultipleRenderTargets=class extends te{constructor(t=1,e=1,i=1,n={}){super(t,e,n),this.isWebGLMultipleRenderTargets=!0;const r=this.texture;this.texture=[];for(let t=0;t 0 ) { ++ ++ prefixVertex = [ ++ '#extension GL_OVR_multiview : require', ++ 'layout(num_views = ' + numMultiviewViews + ') in;', ++ '#define VIEW_ID gl_ViewID_OVR' ++ ].join( '\n' ) + '\n' + prefixVertex; ++ ++ prefixVertex = prefixVertex.replace( ++ [ ++ 'uniform mat4 modelViewMatrix;', ++ 'uniform mat4 projectionMatrix;', ++ 'uniform mat4 viewMatrix;', ++ 'uniform mat3 normalMatrix;' ++ ].join( '\n' ), ++ [ ++ 'uniform mat4 modelViewMatrices[' + numMultiviewViews + '];', ++ 'uniform mat4 projectionMatrices[' + numMultiviewViews + '];', ++ 'uniform mat4 viewMatrices[' + numMultiviewViews + '];', ++ 'uniform mat3 normalMatrices[' + numMultiviewViews + '];', ++ ++ '#define modelViewMatrix modelViewMatrices[VIEW_ID]', ++ '#define projectionMatrix projectionMatrices[VIEW_ID]', ++ '#define viewMatrix viewMatrices[VIEW_ID]', ++ '#define normalMatrix normalMatrices[VIEW_ID]' ++ ].join( '\n' ) ++ ); ++ ++ prefixFragment = [ ++ '#extension GL_OVR_multiview : require', ++ '#define VIEW_ID gl_ViewID_OVR' ++ ].join( '\n' ) + '\n' + prefixFragment; ++ ++ prefixFragment = prefixFragment.replace( ++ 'uniform mat4 viewMatrix;', ++ [ ++ 'uniform mat4 viewMatrices[' + numMultiviewViews + '];', ++ '#define viewMatrix viewMatrices[VIEW_ID]' ++ ].join( '\n' ) ++ ); ++ ++ } ++ + } + + const vertexGlsl = versionString + prefixVertex + vertexShader; +@@ -19086,7 +19133,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { + this.program = program; + this.vertexShader = glVertexShader; + this.fragmentShader = glFragmentShader; +- ++ this.numMultiviewViews = numMultiviewViews; + return this; + + } +@@ -19306,6 +19353,8 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities + + const currentRenderTarget = renderer.getRenderTarget(); + ++ const numMultiviewViews = currentRenderTarget && currentRenderTarget.isWebGLMultiviewRenderTarget ? currentRenderTarget.numViews : 0; ++ + const useAlphaTest = material.alphaTest > 0; + const useClearcoat = material.clearcoat > 0; + const useIridescence = material.iridescence > 0; +@@ -19333,6 +19382,7 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities + instancingColor: object.isInstancedMesh === true && object.instanceColor !== null, + + supportsVertexTextures: vertexTextures, ++ numMultiviewViews: numMultiviewViews, + outputEncoding: ( currentRenderTarget === null ) ? renderer.outputEncoding : ( currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.encoding : LinearEncoding ), + map: !! material.map, + matcap: !! material.matcap, +@@ -19649,6 +19699,8 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities + _programLayers.enable( 23 ); + if ( parameters.opaque ) + _programLayers.enable( 24 ); ++ if ( parameters.numMultiviewViews ) ++ _programLayers.enable( 25 ); + + array.push( _programLayers.mask ); + +@@ -22454,12 +22506,15 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, + const maxSamples = capabilities.maxSamples; + const multisampledRTTExt = extensions.has( 'WEBGL_multisampled_render_to_texture' ) ? extensions.get( 'WEBGL_multisampled_render_to_texture' ) : null; + const supportsInvalidateFramebuffer = typeof navigator === 'undefined' ? false : /OculusBrowser/g.test( navigator.userAgent ); ++ const multiviewExt = extensions.has( 'OCULUS_multiview' ) ? extensions.get( 'OCULUS_multiview' ) : null; + + const _videoTextures = new WeakMap(); + let _canvas; + + const _sources = new WeakMap(); // maps WebglTexture objects to instances of Source + ++ let _deferredUploads = []; ++ + // cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas, + // also OffscreenCanvas.getContext("webgl"), but not OffscreenCanvas.getContext("2d")! + // Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d). +@@ -22896,8 +22951,9 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, + + } else { + +- uploadTexture( textureProperties, texture, slot ); +- return; ++ if ( this.uploadTexture( textureProperties, texture, slot ) ) { ++ return; ++ } + + } + +@@ -22913,7 +22969,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, + + if ( texture.version > 0 && textureProperties.__version !== texture.version ) { + +- uploadTexture( textureProperties, texture, slot ); ++ this.uploadTexture( textureProperties, texture, slot ); + return; + + } +@@ -22928,7 +22984,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, + + if ( texture.version > 0 && textureProperties.__version !== texture.version ) { + +- uploadTexture( textureProperties, texture, slot ); ++ this.uploadTexture( textureProperties, texture, slot ); + return; + + } +@@ -22975,7 +23031,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, + _gl.texParameteri( textureType, 10242, wrappingToGL[ texture.wrapS ] ); + _gl.texParameteri( textureType, 10243, wrappingToGL[ texture.wrapT ] ); + +- if ( textureType === 32879 || textureType === 35866 ) { ++ if ( ( textureType === 32879 || textureType === 35866 ) && texture.wrapR !== undefined ) { + + _gl.texParameteri( textureType, 32882, wrappingToGL[ texture.wrapR ] ); + +@@ -23110,8 +23166,39 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, + + } + ++ function runDeferredUploads() { ++ ++ const previousDeferSetting = this.deferTextureUploads; ++ this.deferTextureUploads = false; ++ ++ for ( const upload of _deferredUploads ) { ++ ++ this.uploadTexture( upload.textureProperties, upload.texture, upload.slot ); ++ upload.texture.isPendingDeferredUpload = false; ++ ++ } ++ ++ _deferredUploads = []; ++ ++ this.deferTextureUploads = previousDeferSetting; ++ ++ } ++ + function uploadTexture( textureProperties, texture, slot ) { + ++ if ( this.deferTextureUploads ) { ++ ++ if ( ! texture.isPendingDeferredUpload ) { ++ ++ texture.isPendingDeferredUpload = true; ++ _deferredUploads.push( { textureProperties: textureProperties, texture: texture, slot: slot } ); ++ ++ } ++ ++ return false; ++ ++ } ++ + let textureType = 3553; + + if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) textureType = 35866; +@@ -23524,7 +23611,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, + } + + textureProperties.__version = texture.version; +- ++ return true; + } + + function uploadCubeTexture( textureProperties, texture, slot ) { +@@ -23746,7 +23833,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, + + if ( ! renderTargetProperties.__hasExternalTextures ) { + +- if ( textureTarget === 32879 || textureTarget === 35866 ) { ++ if ( renderTarget.isWebGLMultiviewRenderTarget === true ) { ++ ++ state.texStorage3D( 35866, 0, glInternalFormat, renderTarget.width, renderTarget.height, renderTarget.numViews ); ++ ++ } else if ( textureTarget === 32879 || textureTarget === 35866 ) { + + state.texImage3D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, renderTarget.depth, 0, glFormat, glType, null ); + +@@ -23760,13 +23851,31 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, + + state.bindFramebuffer( 36160, framebuffer ); + +- if ( useMultisampledRTT( renderTarget ) ) { ++ const multisampled = useMultisampledRTT( renderTarget ); ++ ++ if ( renderTarget.isWebGLMultiviewRenderTarget === true ) { ++ ++ if ( multisampled ) { ++ ++ multiviewExt.framebufferTextureMultisampleMultiviewOVR( 36160, 36064, properties.get( texture ).__webglTexture, 0, getRenderTargetSamples( renderTarget ), 0, renderTarget.numViews ); + +- multisampledRTTExt.framebufferTexture2DMultisampleEXT( 36160, attachment, textureTarget, properties.get( texture ).__webglTexture, 0, getRenderTargetSamples( renderTarget ) ); ++ } else { ++ ++ multiviewExt.framebufferTextureMultiviewOVR( 36160, 36064, properties.get( texture ).__webglTexture, 0, 0, renderTarget.numViews ); ++ ++ } + + } else if ( textureTarget === 3553 || ( textureTarget >= 34069 && textureTarget <= 34074 ) ) { // see #24753 + +- _gl.framebufferTexture2D( 36160, attachment, textureTarget, properties.get( texture ).__webglTexture, 0 ); ++ if ( multisampled ) { ++ ++ multisampledRTTExt.framebufferTexture2DMultisampleEXT( 36160, attachment, textureTarget, properties.get( texture ).__webglTexture, 0, getRenderTargetSamples( renderTarget ) ); ++ ++ } else { ++ ++ _gl.framebufferTexture2D( 36160, attachment, textureTarget, properties.get( texture ).__webglTexture, 0 ); ++ ++ } + + } + +@@ -23774,13 +23883,83 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, + + } + ++ // rebind framebuffer with external textures ++ function rebindTextures( renderTarget, colorTexture, depthTexture ) { ++ ++ const renderTargetProperties = properties.get( renderTarget ); ++ ++ if ( colorTexture !== undefined ) { ++ ++ this.setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, renderTarget.texture, 36064, 3553 ); ++ ++ } ++ ++ if ( depthTexture !== undefined ) { ++ ++ this.setupDepthRenderbuffer( renderTarget ); ++ ++ } ++ ++ } + + // Setup storage for internal depth/stencil buffers and bind to correct framebuffer + function setupRenderBufferStorage( renderbuffer, renderTarget, isMultisample ) { + + _gl.bindRenderbuffer( 36161, renderbuffer ); + +- if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) { ++ if ( renderTarget.isWebGLMultiviewRenderTarget === true ) { ++ ++ const useMultisample = useMultisampledRTT( renderTarget ); ++ const numViews = renderTarget.numViews; ++ ++ const depthTexture = renderTarget.depthTexture; ++ let glInternalFormat = 33190; ++ let glDepthAttachment = 36096; ++ ++ if ( depthTexture && depthTexture.isDepthTexture ) { ++ ++ if ( depthTexture.type === FloatType ) { ++ ++ glInternalFormat = 36012; ++ ++ } else if ( depthTexture.type === UnsignedInt248Type ) { ++ ++ glInternalFormat = 35056; ++ glDepthAttachment = 33306; ++ ++ } ++ ++ // we're defaulting to 33190 so don't assign here ++ // or else DeepScan will complain ++ ++ // else if ( depthTexture.type === UnsignedIntType ) { ++ ++ // glInternalFormat = 33190; ++ ++ // } ++ ++ } ++ ++ let depthStencilTexture = properties.get( renderTarget.depthTexture ).__webglTexture; ++ if ( depthStencilTexture === undefined ) { ++ ++ depthStencilTexture = _gl.createTexture(); ++ _gl.bindTexture( 35866, depthStencilTexture ); ++ _gl.texStorage3D( 35866, 1, glInternalFormat, renderTarget.width, renderTarget.height, numViews ); ++ ++ } ++ ++ if ( useMultisample ) { ++ ++ multiviewExt.framebufferTextureMultisampleMultiviewOVR( 36160, glDepthAttachment, depthStencilTexture, 0, getRenderTargetSamples( renderTarget ), 0, numViews ); ++ ++ } else { ++ ++ multiviewExt.framebufferTextureMultiviewOVR( 36160, glDepthAttachment, depthStencilTexture, 0, 0, numViews ); ++ ++ } ++ ++ } else if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) { + + let glInternalFormat = 33189; + +@@ -23903,38 +24082,84 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, + + } + +- setTexture2D( renderTarget.depthTexture, 0 ); ++ if ( renderTarget.depthTexture.image.depth != 1 ) { ++ ++ this.setTexture2DArray( renderTarget.depthTexture, 0 ); ++ ++ } else { ++ ++ this.setTexture2D( renderTarget.depthTexture, 0 ); ++ ++ } + + const webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture; + const samples = getRenderTargetSamples( renderTarget ); + +- if ( renderTarget.depthTexture.format === DepthFormat ) { ++ if ( renderTarget.isWebGLMultiviewRenderTarget === true ) { + +- if ( useMultisampledRTT( renderTarget ) ) { ++ const useMultisample = useMultisampledRTT( renderTarget ); ++ const numViews = renderTarget.numViews; + +- multisampledRTTExt.framebufferTexture2DMultisampleEXT( 36160, 36096, 3553, webglDepthTexture, 0, samples ); ++ if ( renderTarget.depthTexture.format === DepthFormat ) { + +- } else { ++ if ( useMultisample ) { + +- _gl.framebufferTexture2D( 36160, 36096, 3553, webglDepthTexture, 0 ); ++ multiviewExt.framebufferTextureMultisampleMultiviewOVR( 36160, 36096, webglDepthTexture, 0, samples, 0, numViews ); + +- } ++ } else { + +- } else if ( renderTarget.depthTexture.format === DepthStencilFormat ) { ++ multiviewExt.framebufferTextureMultiviewOVR( 36160, 36096, webglDepthTexture, 0, 0, numViews ); + +- if ( useMultisampledRTT( renderTarget ) ) { ++ } ++ ++ } else if ( renderTarget.depthTexture.format === DepthStencilFormat ) { + +- multisampledRTTExt.framebufferTexture2DMultisampleEXT( 36160, 33306, 3553, webglDepthTexture, 0, samples ); ++ if ( useMultisample ) { ++ ++ multiviewExt.framebufferTextureMultisampleMultiviewOVR( 36160, 33306, webglDepthTexture, 0, samples, 0, numViews ); ++ ++ } else { ++ ++ multiviewExt.framebufferTextureMultiviewOVR( 36160, 33306, webglDepthTexture, 0, 0, numViews ); ++ ++ } + + } else { + +- _gl.framebufferTexture2D( 36160, 33306, 3553, webglDepthTexture, 0 ); ++ throw new Error( 'Unknown depthTexture format' ); + + } + + } else { ++ if ( renderTarget.depthTexture.format === DepthFormat ) { ++ ++ if ( useMultisampledRTT( renderTarget ) ) { ++ ++ multisampledRTTExt.framebufferTexture2DMultisampleEXT( 36160, 36096, 3553, webglDepthTexture, 0, samples ); ++ ++ } else { ++ ++ _gl.framebufferTexture2D( 36160, 36096, 3553, webglDepthTexture, 0 ); ++ ++ } ++ ++ } else if ( renderTarget.depthTexture.format === DepthStencilFormat ) { ++ ++ if ( useMultisampledRTT( renderTarget ) ) { ++ ++ multisampledRTTExt.framebufferTexture2DMultisampleEXT( 36160, 33306, 3553, webglDepthTexture, 0, samples ); ++ ++ } else { + +- throw new Error( 'Unknown depthTexture format' ); ++ _gl.framebufferTexture2D( 36160, 33306, 3553, webglDepthTexture, 0 ); ++ ++ } ++ ++ } else { ++ ++ throw new Error( 'Unknown depthTexture format' ); ++ ++ } + + } + +@@ -23950,7 +24175,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, + + if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' ); + +- setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget ); ++ this.setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget ); + + } else { + +@@ -23980,24 +24205,6 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, + + } + +- // rebind framebuffer with external textures +- function rebindTextures( renderTarget, colorTexture, depthTexture ) { +- +- const renderTargetProperties = properties.get( renderTarget ); +- +- if ( colorTexture !== undefined ) { +- +- setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, renderTarget.texture, 36064, 3553 ); +- +- } +- +- if ( depthTexture !== undefined ) { +- +- setupDepthRenderbuffer( renderTarget ); +- +- } +- +- } + + // Set up GL resources for the render target + function setupRenderTarget( renderTarget ) { +@@ -24173,6 +24380,12 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, + + } + ++ if ( renderTarget.isWebGLMultiviewRenderTarget === true ) { ++ ++ glTextureType = 35866; ++ ++ } ++ + state.bindTexture( glTextureType, textureProperties.__webglTexture ); + setTextureParameters( glTextureType, texture, supportsMips ); + setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, texture, 36064, glTextureType ); +@@ -24189,9 +24402,9 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, + + // Setup depth and stencil buffers + +- if ( renderTarget.depthBuffer ) { ++ if ( renderTarget.depthBuffer || renderTarget.isWebGLMultiviewRenderTarget === true ) { + +- setupDepthRenderbuffer( renderTarget ); ++ this.setupDepthRenderbuffer( renderTarget ); + + } + +@@ -24427,12 +24640,15 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, + this.setTexture3D = setTexture3D; + this.setTextureCube = setTextureCube; + this.rebindTextures = rebindTextures; ++ this.uploadTexture = uploadTexture; + this.setupRenderTarget = setupRenderTarget; + this.updateRenderTargetMipmap = updateRenderTargetMipmap; + this.updateMultisampleRenderTarget = updateMultisampleRenderTarget; ++ this.setupDepthTexture = setupDepthTexture; + this.setupDepthRenderbuffer = setupDepthRenderbuffer; + this.setupFrameBufferTexture = setupFrameBufferTexture; + this.useMultisampledRTT = useMultisampledRTT; ++ this.runDeferredUploads = runDeferredUploads; + + } + +@@ -24698,6 +24914,104 @@ function WebGLUtils( gl, extensions, capabilities ) { + + } + ++/** ++ * @author fernandojsg / http://fernandojsg.com ++ * @author Takahiro https://github.com/takahirox ++ */ ++ ++ ++class WebGLMultiview { ++ ++ constructor( renderer, extensions, gl ) { ++ ++ this.renderer = renderer; ++ ++ this.DEFAULT_NUMVIEWS = 2; ++ this.maxNumViews = 0; ++ this.gl = gl; ++ ++ this.extensions = extensions; ++ ++ this.available = this.extensions.has( 'OCULUS_multiview' ); ++ ++ if ( this.available ) { ++ ++ const extension = this.extensions.get( 'OCULUS_multiview' ); ++ ++ this.maxNumViews = this.gl.getParameter( extension.MAX_VIEWS_OVR ); ++ ++ this.mat4 = []; ++ this.mat3 = []; ++ this.cameraArray = []; ++ ++ for ( var i = 0; i < this.maxNumViews; i ++ ) { ++ ++ this.mat4[ i ] = new Matrix4(); ++ this.mat3[ i ] = new Matrix3(); ++ ++ } ++ ++ } ++ ++ } ++ ++ // ++ getCameraArray( camera ) { ++ ++ if ( camera.isArrayCamera ) return camera.cameras; ++ ++ this.cameraArray[ 0 ] = camera; ++ ++ return this.cameraArray; ++ ++ } ++ ++ updateCameraProjectionMatricesUniform( camera, uniforms ) { ++ ++ var cameras = this.getCameraArray( camera ); ++ ++ for ( var i = 0; i < cameras.length; i ++ ) { ++ ++ this.mat4[ i ].copy( cameras[ i ].projectionMatrix ); ++ ++ } ++ ++ uniforms.setValue( this.gl, 'projectionMatrices', this.mat4 ); ++ ++ } ++ ++ updateCameraViewMatricesUniform( camera, uniforms ) { ++ ++ var cameras = this.getCameraArray( camera ); ++ ++ for ( var i = 0; i < cameras.length; i ++ ) { ++ ++ this.mat4[ i ].copy( cameras[ i ].matrixWorldInverse ); ++ ++ } ++ ++ uniforms.setValue( this.gl, 'viewMatrices', this.mat4 ); ++ ++ } ++ ++ updateObjectMatricesUniforms( object, camera, uniforms ) { ++ ++ var cameras = this.getCameraArray( camera ); ++ ++ for ( var i = 0; i < cameras.length; i ++ ) { ++ ++ this.mat4[ i ].multiplyMatrices( cameras[ i ].matrixWorldInverse, object.matrixWorld ); ++ this.mat3[ i ].getNormalMatrix( this.mat4[ i ] ); ++ ++ } ++ ++ uniforms.setValue( this.gl, 'modelViewMatrices', this.mat4 ); ++ uniforms.setValue( this.gl, 'normalMatrices', this.mat3 ); ++ ++ } ++ ++} ++ + class Group extends Object3D { + + constructor() { +@@ -25259,6 +25573,38 @@ Object.assign( WebVRManager.prototype, { + dispatchEvent: EventDispatcher.prototype.dispatchEvent + } ); + ++/** ++ * @author fernandojsg / http://fernandojsg.com ++ * @author Takahiro https://github.com/takahirox ++ */ ++ ++class WebGLMultiviewRenderTarget extends WebGLRenderTarget { ++ ++ constructor( width, height, numViews, options = {} ) { ++ ++ super( width, height, options ); ++ ++ this.depthBuffer = false; ++ this.stencilBuffer = false; ++ ++ this.numViews = numViews; ++ ++ } ++ ++ copy( source ) { ++ ++ super.copy( source ); ++ ++ this.numViews = source.numViews; ++ ++ return this; ++ ++ } ++ ++} ++ ++WebGLMultiviewRenderTarget.prototype.isWebGLMultiviewRenderTarget = true; ++ + const _moveEvent = { type: 'move' }; + + class WebXRController { +@@ -25628,7 +25974,7 @@ class DepthTexture extends Texture { + + class WebXRManager extends EventDispatcher { + +- constructor( renderer, gl ) { ++ constructor( renderer, gl, extensions, useMultiview ) { + + super(); + +@@ -25684,6 +26030,7 @@ class WebXRManager extends EventDispatcher { + this.enabled = false; + + this.isPresenting = false; ++ this.isMultiview = false; + + this.getCameraPose = function ( ) { + +@@ -25926,29 +26273,51 @@ class WebXRManager extends EventDispatcher { + + } + ++ scope.isMultiview = useMultiview && extensions.has( 'OCULUS_multiview' ); + const projectionlayerInit = { + colorFormat: 32856, + depthFormat: glDepthFormat, + scaleFactor: framebufferScaleFactor + }; + ++ if ( scope.isMultiview ) { ++ ++ projectionlayerInit.textureType = 'texture-array'; ++ ++ } ++ + glBinding = new XRWebGLBinding( session, gl ); + + glProjLayer = glBinding.createProjectionLayer( projectionlayerInit ); + + session.updateRenderState( { layers: [ glProjLayer ] } ); + +- newRenderTarget = new WebGLRenderTarget( +- glProjLayer.textureWidth, +- glProjLayer.textureHeight, +- { +- format: RGBAFormat, +- type: UnsignedByteType, +- depthTexture: new DepthTexture( glProjLayer.textureWidth, glProjLayer.textureHeight, depthType, undefined, undefined, undefined, undefined, undefined, undefined, depthFormat ), +- stencilBuffer: attributes.stencil, +- encoding: renderer.outputEncoding, +- samples: attributes.antialias ? 4 : 0 +- } ); ++ const rtOptions = { ++ format: RGBAFormat, ++ type: UnsignedByteType, ++ depthTexture: new DepthTexture( glProjLayer.textureWidth, glProjLayer.textureHeight, depthType, undefined, undefined, undefined, undefined, undefined, undefined, depthFormat ), ++ stencilBuffer: attributes.stencil, ++ encoding: renderer.outputEncoding, ++ samples: attributes.antialias ? 4 : 0 ++ }; ++ ++ if ( scope.isMultiview ) { ++ ++ const extension = extensions.get( 'OCULUS_multiview' ); ++ ++ this.maxNumViews = gl.getParameter( extension.MAX_VIEWS_OVR ); ++ ++ newRenderTarget = new WebGLMultiviewRenderTarget( glProjLayer.textureWidth, glProjLayer.textureHeight, 2, rtOptions ); ++ ++ } else { ++ ++ newRenderTarget = new WebGLRenderTarget( ++ glProjLayer.textureWidth, ++ glProjLayer.textureHeight, ++ rtOptions ); ++ ++ } ++ + + const renderTargetProperties = renderer.properties.get( newRenderTarget ); + renderTargetProperties.__ignoreDepthValues = glProjLayer.ignoreDepthValues; +@@ -27509,7 +27878,8 @@ function WebGLRenderer( parameters = {} ) { + _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true, + _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false, + _powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default', +- _failIfMajorPerformanceCaveat = parameters.failIfMajorPerformanceCaveat !== undefined ? parameters.failIfMajorPerformanceCaveat : false; ++ _failIfMajorPerformanceCaveat = parameters.failIfMajorPerformanceCaveat !== undefined ? parameters.failIfMajorPerformanceCaveat : false, ++ _multiviewStereo = parameters.multiviewStereo !== undefined ? parameters.multiviewStereo : false; + + let _alpha; + +@@ -27724,6 +28094,7 @@ function WebGLRenderer( parameters = {} ) { + let extensions, capabilities, state, info; + let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects; + let programCache, materials, renderLists, renderStates, clipping, shadowMap; ++ let multiview; + + let background, morphtargets, bufferRenderer, indexedBufferRenderer; + +@@ -27753,6 +28124,7 @@ function WebGLRenderer( parameters = {} ) { + morphtargets = new WebGLMorphtargets( _gl, capabilities, textures ); + clipping = new WebGLClipping( properties ); + programCache = new WebGLPrograms( _this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ); ++ multiview = new WebGLMultiview( _this, extensions, _gl ); + materials = new WebGLMaterials( _this, properties ); + renderLists = new WebGLRenderLists(); + renderStates = new WebGLRenderStates( extensions, capabilities ); +@@ -27777,7 +28149,7 @@ function WebGLRenderer( parameters = {} ) { + + initGLContext(); + +- const xr = ( typeof navigator !== 'undefined' && 'xr' in navigator ) ? new WebXRManager( _this, _gl ) : new WebVRManager( _this ); ++ const xr = ( typeof navigator !== 'undefined' && 'xr' in navigator ) ? new WebXRManager( _this, _gl, extensions, _multiviewStereo ) : new WebVRManager( _this ); + + this.xr = xr; + +@@ -28462,14 +28834,23 @@ function WebGLRenderer( parameters = {} ) { + + if ( camera.isArrayCamera ) { + +- const cameras = camera.cameras; ++ if ( xr.enabled && xr.isMultiview ) { ++ ++ textures.deferTextureUploads = true; ++ ++ renderScene( currentRenderList, scene, camera, camera.cameras[ 0 ].viewport ); ++ ++ } else { ++ ++ const cameras = camera.cameras; + +- for ( let i = 0, l = cameras.length; i < l; i ++ ) { ++ for ( let i = 0, l = cameras.length; i < l; i ++ ) { + +- const camera2 = cameras[ i ]; ++ const camera2 = cameras[ i ]; + +- renderScene( currentRenderList, scene, camera2, camera2.viewport ); ++ renderScene( currentRenderList, scene, camera2, camera2.viewport ); + ++ } + } + + } else { +@@ -28501,6 +28882,7 @@ function WebGLRenderer( parameters = {} ) { + xr.submitFrame(); + + } ++ textures.runDeferredUploads(); + // _gl.finish(); + + bindingStates.resetDefaultState(); +@@ -28907,6 +29289,7 @@ function WebGLRenderer( parameters = {} ) { + materialProperties.vertexAlphas = parameters.vertexAlphas; + materialProperties.vertexTangents = parameters.vertexTangents; + materialProperties.toneMapping = parameters.toneMapping; ++ materialProperties.numMultiviewViews = parameters.numMultiviewViews; + + } + +@@ -28927,6 +29310,8 @@ function WebGLRenderer( parameters = {} ) { + const morphColors = !! geometry.morphAttributes.color; + const toneMapping = material.toneMapped ? _this.toneMapping : NoToneMapping; + ++ const numMultiviewViews = _currentRenderTarget && _currentRenderTarget.isWebGLMultiviewRenderTarget ? _currentRenderTarget.numViews : 0; ++ + const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; + const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; + +@@ -29022,6 +29407,10 @@ function WebGLRenderer( parameters = {} ) { + + needsProgramChange = true; + ++ } else if ( materialProperties.numMultiviewViews !== numMultiviewViews ) { ++ ++ needsProgramChange = true; ++ + } + + } else { +@@ -29066,7 +29455,15 @@ function WebGLRenderer( parameters = {} ) { + + if ( refreshProgram || _currentCamera !== camera ) { + +- p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix ); ++ if ( program.numMultiviewViews > 0 ) { ++ ++ multiview.updateCameraProjectionMatricesUniform( camera, p_uniforms ); ++ ++ } else { ++ ++ p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix ); ++ ++ } + + if ( capabilities.logarithmicDepthBuffer ) { + +@@ -29128,7 +29525,15 @@ function WebGLRenderer( parameters = {} ) { + material.isShadowMaterial || + object.isSkinnedMesh ) { + +- p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse ); ++ if ( program.numMultiviewViews > 0 ) { ++ ++ multiview.updateCameraViewMatricesUniform( camera, p_uniforms ); ++ ++ } else { ++ ++ p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse ); ++ ++ } + + } + +@@ -29237,8 +29642,16 @@ function WebGLRenderer( parameters = {} ) { + + // common matrices + +- p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix ); +- p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix ); ++ if ( program.numMultiviewViews > 0 ) { ++ ++ multiview.updateObjectMatricesUniforms( object, camera, p_uniforms ); ++ ++ } else { ++ ++ p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix ); ++ p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix ); ++ ++ } + p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld ); + + // UBOs +@@ -29348,20 +29761,16 @@ function WebGLRenderer( parameters = {} ) { + const renderTargetProperties = properties.get( renderTarget ); + renderTargetProperties.__hasExternalTextures = true; + +- if ( renderTargetProperties.__hasExternalTextures ) { +- +- renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === undefined; ++ renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === undefined; + +- if ( ! renderTargetProperties.__autoAllocateDepthBuffer ) { ++ if ( ! renderTargetProperties.__autoAllocateDepthBuffer && ! _currentRenderTarget.isWebGLMultiviewRenderTarget ) { + +- // The multisample_render_to_texture extension doesn't work properly if there +- // are midframe flushes and an external depth buffer. Disable use of the extension. +- if ( extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true ) { ++ // The multisample_render_to_texture extension doesn't work properly if there ++ // are midframe flushes and an external depth buffer. Disable use of the extension. ++ if ( extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true ) { + +- console.warn( 'THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided' ); +- renderTargetProperties.__useRenderToTexture = false; +- +- } ++ console.warn( 'THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided' ); ++ renderTargetProperties.__useRenderToTexture = false; + + } + From c2b1518b363cc2ebb6ce93cdf61cfe397704f42a Mon Sep 17 00:00:00 2001 From: trichu Date: Tue, 9 May 2023 16:02:39 -0700 Subject: [PATCH 2/2] build dist/8frame files --- dist/8frame-1.4.1.js | 45628 +++++++++++++++++++++++++++++++++ dist/8frame-1.4.1.js.map | 1 + dist/8frame-1.4.1.min.js | 2 + dist/8frame-1.4.1.min.js.map | 1 + package.json | 2 +- src/index.js | 2 +- 6 files changed, 45634 insertions(+), 2 deletions(-) create mode 100644 dist/8frame-1.4.1.js create mode 100644 dist/8frame-1.4.1.js.map create mode 100644 dist/8frame-1.4.1.min.js create mode 100644 dist/8frame-1.4.1.min.js.map diff --git a/dist/8frame-1.4.1.js b/dist/8frame-1.4.1.js new file mode 100644 index 00000000000..25bf049642a --- /dev/null +++ b/dist/8frame-1.4.1.js @@ -0,0 +1,45628 @@ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["AFRAME"] = factory(); + else + root["AFRAME"] = factory(); +})(self, () => { +return /******/ (() => { // webpackBootstrap +/******/ var __webpack_modules__ = ({ + +/***/ "./node_modules/@ungap/custom-elements/index.js": +/*!******************************************************!*\ + !*** ./node_modules/@ungap/custom-elements/index.js ***! + \******************************************************/ +/***/ (() => { + +/*! (c) Andrea Giammarchi @webreflection ISC */ +(function () { + 'use strict'; + + var attributesObserver = function (whenDefined, MutationObserver) { + var attributeChanged = function attributeChanged(records) { + for (var i = 0, length = records.length; i < length; i++) dispatch(records[i]); + }; + var dispatch = function dispatch(_ref) { + var target = _ref.target, + attributeName = _ref.attributeName, + oldValue = _ref.oldValue; + target.attributeChangedCallback(attributeName, oldValue, target.getAttribute(attributeName)); + }; + return function (target, is) { + var attributeFilter = target.constructor.observedAttributes; + if (attributeFilter) { + whenDefined(is).then(function () { + new MutationObserver(attributeChanged).observe(target, { + attributes: true, + attributeOldValue: true, + attributeFilter: attributeFilter + }); + for (var i = 0, length = attributeFilter.length; i < length; i++) { + if (target.hasAttribute(attributeFilter[i])) dispatch({ + target: target, + attributeName: attributeFilter[i], + oldValue: null + }); + } + }); + } + return target; + }; + }; + function _unsupportedIterableToArray(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); + } + function _arrayLikeToArray(arr, len) { + if (len == null || len > arr.length) len = arr.length; + for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + return arr2; + } + function _createForOfIteratorHelper(o, allowArrayLike) { + var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; + if (!it) { + if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { + if (it) o = it; + var i = 0; + var F = function () {}; + return { + s: F, + n: function () { + if (i >= o.length) return { + done: true + }; + return { + done: false, + value: o[i++] + }; + }, + e: function (e) { + throw e; + }, + f: F + }; + } + throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + var normalCompletion = true, + didErr = false, + err; + return { + s: function () { + it = it.call(o); + }, + n: function () { + var step = it.next(); + normalCompletion = step.done; + return step; + }, + e: function (e) { + didErr = true; + err = e; + }, + f: function () { + try { + if (!normalCompletion && it.return != null) it.return(); + } finally { + if (didErr) throw err; + } + } + }; + } + + /*! (c) Andrea Giammarchi - ISC */ + var TRUE = true, + FALSE = false, + QSA$1 = 'querySelectorAll'; + + /** + * Start observing a generic document or root element. + * @param {(node:Element, connected:boolean) => void} callback triggered per each dis/connected element + * @param {Document|Element} [root=document] by default, the global document to observe + * @param {Function} [MO=MutationObserver] by default, the global MutationObserver + * @param {string[]} [query=['*']] the selectors to use within nodes + * @returns {MutationObserver} + */ + var notify = function notify(callback) { + var root = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : document; + var MO = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : MutationObserver; + var query = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : ['*']; + var loop = function loop(nodes, selectors, added, removed, connected, pass) { + var _iterator = _createForOfIteratorHelper(nodes), + _step; + try { + for (_iterator.s(); !(_step = _iterator.n()).done;) { + var node = _step.value; + if (pass || QSA$1 in node) { + if (connected) { + if (!added.has(node)) { + added.add(node); + removed["delete"](node); + callback(node, connected); + } + } else if (!removed.has(node)) { + removed.add(node); + added["delete"](node); + callback(node, connected); + } + if (!pass) loop(node[QSA$1](selectors), selectors, added, removed, connected, TRUE); + } + } + } catch (err) { + _iterator.e(err); + } finally { + _iterator.f(); + } + }; + var mo = new MO(function (records) { + if (query.length) { + var selectors = query.join(','); + var added = new Set(), + removed = new Set(); + var _iterator2 = _createForOfIteratorHelper(records), + _step2; + try { + for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { + var _step2$value = _step2.value, + addedNodes = _step2$value.addedNodes, + removedNodes = _step2$value.removedNodes; + loop(removedNodes, selectors, added, removed, FALSE, FALSE); + loop(addedNodes, selectors, added, removed, TRUE, FALSE); + } + } catch (err) { + _iterator2.e(err); + } finally { + _iterator2.f(); + } + } + }); + var observe = mo.observe; + (mo.observe = function (node) { + return observe.call(mo, node, { + subtree: TRUE, + childList: TRUE + }); + })(root); + return mo; + }; + var QSA = 'querySelectorAll'; + var _self$1 = self, + document$2 = _self$1.document, + Element$1 = _self$1.Element, + MutationObserver$2 = _self$1.MutationObserver, + Set$2 = _self$1.Set, + WeakMap$1 = _self$1.WeakMap; + var elements = function elements(element) { + return QSA in element; + }; + var filter = [].filter; + var qsaObserver = function (options) { + var live = new WeakMap$1(); + var drop = function drop(elements) { + for (var i = 0, length = elements.length; i < length; i++) live["delete"](elements[i]); + }; + var flush = function flush() { + var records = observer.takeRecords(); + for (var i = 0, length = records.length; i < length; i++) { + parse(filter.call(records[i].removedNodes, elements), false); + parse(filter.call(records[i].addedNodes, elements), true); + } + }; + var matches = function matches(element) { + return element.matches || element.webkitMatchesSelector || element.msMatchesSelector; + }; + var notifier = function notifier(element, connected) { + var selectors; + if (connected) { + for (var q, m = matches(element), i = 0, length = query.length; i < length; i++) { + if (m.call(element, q = query[i])) { + if (!live.has(element)) live.set(element, new Set$2()); + selectors = live.get(element); + if (!selectors.has(q)) { + selectors.add(q); + options.handle(element, connected, q); + } + } + } + } else if (live.has(element)) { + selectors = live.get(element); + live["delete"](element); + selectors.forEach(function (q) { + options.handle(element, connected, q); + }); + } + }; + var parse = function parse(elements) { + var connected = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + for (var i = 0, length = elements.length; i < length; i++) notifier(elements[i], connected); + }; + var query = options.query; + var root = options.root || document$2; + var observer = notify(notifier, root, MutationObserver$2, query); + var attachShadow = Element$1.prototype.attachShadow; + if (attachShadow) Element$1.prototype.attachShadow = function (init) { + var shadowRoot = attachShadow.call(this, init); + observer.observe(shadowRoot); + return shadowRoot; + }; + if (query.length) parse(root[QSA](query)); + return { + drop: drop, + flush: flush, + observer: observer, + parse: parse + }; + }; + var _self = self, + document$1 = _self.document, + Map = _self.Map, + MutationObserver$1 = _self.MutationObserver, + Object$1 = _self.Object, + Set$1 = _self.Set, + WeakMap = _self.WeakMap, + Element = _self.Element, + HTMLElement = _self.HTMLElement, + Node = _self.Node, + Error = _self.Error, + TypeError$1 = _self.TypeError, + Reflect = _self.Reflect; + var defineProperty = Object$1.defineProperty, + keys = Object$1.keys, + getOwnPropertyNames = Object$1.getOwnPropertyNames, + setPrototypeOf = Object$1.setPrototypeOf; + var legacy = !self.customElements; + var expando = function expando(element) { + var key = keys(element); + var value = []; + var length = key.length; + for (var i = 0; i < length; i++) { + value[i] = element[key[i]]; + delete element[key[i]]; + } + return function () { + for (var _i = 0; _i < length; _i++) element[key[_i]] = value[_i]; + }; + }; + if (legacy) { + var HTMLBuiltIn = function HTMLBuiltIn() { + var constructor = this.constructor; + if (!classes.has(constructor)) throw new TypeError$1('Illegal constructor'); + var is = classes.get(constructor); + if (override) return augment(override, is); + var element = createElement.call(document$1, is); + return augment(setPrototypeOf(element, constructor.prototype), is); + }; + var createElement = document$1.createElement; + var classes = new Map(); + var defined = new Map(); + var prototypes = new Map(); + var registry = new Map(); + var query = []; + var handle = function handle(element, connected, selector) { + var proto = prototypes.get(selector); + if (connected && !proto.isPrototypeOf(element)) { + var redefine = expando(element); + override = setPrototypeOf(element, proto); + try { + new proto.constructor(); + } finally { + override = null; + redefine(); + } + } + var method = "".concat(connected ? '' : 'dis', "connectedCallback"); + if (method in proto) element[method](); + }; + var _qsaObserver = qsaObserver({ + query: query, + handle: handle + }), + parse = _qsaObserver.parse; + var override = null; + var whenDefined = function whenDefined(name) { + if (!defined.has(name)) { + var _, + $ = new Promise(function ($) { + _ = $; + }); + defined.set(name, { + $: $, + _: _ + }); + } + return defined.get(name).$; + }; + var augment = attributesObserver(whenDefined, MutationObserver$1); + self.customElements = { + define: function define(is, Class) { + if (registry.has(is)) throw new Error("the name \"".concat(is, "\" has already been used with this registry")); + classes.set(Class, is); + prototypes.set(is, Class.prototype); + registry.set(is, Class); + query.push(is); + whenDefined(is).then(function () { + parse(document$1.querySelectorAll(is)); + }); + defined.get(is)._(Class); + }, + get: function get(is) { + return registry.get(is); + }, + whenDefined: whenDefined + }; + defineProperty(HTMLBuiltIn.prototype = HTMLElement.prototype, 'constructor', { + value: HTMLBuiltIn + }); + self.HTMLElement = HTMLBuiltIn; + document$1.createElement = function (name, options) { + var is = options && options.is; + var Class = is ? registry.get(is) : registry.get(name); + return Class ? new Class() : createElement.call(document$1, name); + }; + // in case ShadowDOM is used through a polyfill, to avoid issues + // with builtin extends within shadow roots + if (!('isConnected' in Node.prototype)) defineProperty(Node.prototype, 'isConnected', { + configurable: true, + get: function get() { + return !(this.ownerDocument.compareDocumentPosition(this) & this.DOCUMENT_POSITION_DISCONNECTED); + } + }); + } else { + legacy = !self.customElements.get('extends-li'); + if (legacy) { + try { + var LI = function LI() { + return self.Reflect.construct(HTMLLIElement, [], LI); + }; + LI.prototype = HTMLLIElement.prototype; + var is = 'extends-li'; + self.customElements.define('extends-li', LI, { + 'extends': 'li' + }); + legacy = document$1.createElement('li', { + is: is + }).outerHTML.indexOf(is) < 0; + var _self$customElements = self.customElements, + get = _self$customElements.get, + _whenDefined = _self$customElements.whenDefined; + self.customElements.whenDefined = function (is) { + var _this = this; + return _whenDefined.call(this, is).then(function (Class) { + return Class || get.call(_this, is); + }); + }; + } catch (o_O) {} + } + } + if (legacy) { + var _parseShadow = function _parseShadow(element) { + var root = shadowRoots.get(element); + _parse(root.querySelectorAll(this), element.isConnected); + }; + var customElements = self.customElements; + var _createElement = document$1.createElement; + var define = customElements.define, + _get = customElements.get, + upgrade = customElements.upgrade; + var _ref = Reflect || { + construct: function construct(HTMLElement) { + return HTMLElement.call(this); + } + }, + construct = _ref.construct; + var shadowRoots = new WeakMap(); + var shadows = new Set$1(); + var _classes = new Map(); + var _defined = new Map(); + var _prototypes = new Map(); + var _registry = new Map(); + var shadowed = []; + var _query = []; + var getCE = function getCE(is) { + return _registry.get(is) || _get.call(customElements, is); + }; + var _handle = function _handle(element, connected, selector) { + var proto = _prototypes.get(selector); + if (connected && !proto.isPrototypeOf(element)) { + var redefine = expando(element); + _override = setPrototypeOf(element, proto); + try { + new proto.constructor(); + } finally { + _override = null; + redefine(); + } + } + var method = "".concat(connected ? '' : 'dis', "connectedCallback"); + if (method in proto) element[method](); + }; + var _qsaObserver2 = qsaObserver({ + query: _query, + handle: _handle + }), + _parse = _qsaObserver2.parse; + var _qsaObserver3 = qsaObserver({ + query: shadowed, + handle: function handle(element, connected) { + if (shadowRoots.has(element)) { + if (connected) shadows.add(element);else shadows["delete"](element); + if (_query.length) _parseShadow.call(_query, element); + } + } + }), + parseShadowed = _qsaObserver3.parse; + // qsaObserver also patches attachShadow + // be sure this runs *after* that + var attachShadow = Element.prototype.attachShadow; + if (attachShadow) Element.prototype.attachShadow = function (init) { + var root = attachShadow.call(this, init); + shadowRoots.set(this, root); + return root; + }; + var _whenDefined2 = function _whenDefined2(name) { + if (!_defined.has(name)) { + var _, + $ = new Promise(function ($) { + _ = $; + }); + _defined.set(name, { + $: $, + _: _ + }); + } + return _defined.get(name).$; + }; + var _augment = attributesObserver(_whenDefined2, MutationObserver$1); + var _override = null; + getOwnPropertyNames(self).filter(function (k) { + return /^HTML.*Element$/.test(k); + }).forEach(function (k) { + var HTMLElement = self[k]; + function HTMLBuiltIn() { + var constructor = this.constructor; + if (!_classes.has(constructor)) throw new TypeError$1('Illegal constructor'); + var _classes$get = _classes.get(constructor), + is = _classes$get.is, + tag = _classes$get.tag; + if (is) { + if (_override) return _augment(_override, is); + var element = _createElement.call(document$1, tag); + element.setAttribute('is', is); + return _augment(setPrototypeOf(element, constructor.prototype), is); + } else return construct.call(this, HTMLElement, [], constructor); + } + defineProperty(HTMLBuiltIn.prototype = HTMLElement.prototype, 'constructor', { + value: HTMLBuiltIn + }); + defineProperty(self, k, { + value: HTMLBuiltIn + }); + }); + document$1.createElement = function (name, options) { + var is = options && options.is; + if (is) { + var Class = _registry.get(is); + if (Class && _classes.get(Class).tag === name) return new Class(); + } + var element = _createElement.call(document$1, name); + if (is) element.setAttribute('is', is); + return element; + }; + customElements.get = getCE; + customElements.whenDefined = _whenDefined2; + customElements.upgrade = function (element) { + var is = element.getAttribute('is'); + if (is) { + var _constructor = _registry.get(is); + if (_constructor) { + _augment(setPrototypeOf(element, _constructor.prototype), is); + // apparently unnecessary because this is handled by qsa observer + // if (element.isConnected && element.connectedCallback) + // element.connectedCallback(); + return; + } + } + upgrade.call(customElements, element); + }; + customElements.define = function (is, Class, options) { + if (getCE(is)) throw new Error("'".concat(is, "' has already been defined as a custom element")); + var selector; + var tag = options && options["extends"]; + _classes.set(Class, tag ? { + is: is, + tag: tag + } : { + is: '', + tag: is + }); + if (tag) { + selector = "".concat(tag, "[is=\"").concat(is, "\"]"); + _prototypes.set(selector, Class.prototype); + _registry.set(is, Class); + _query.push(selector); + } else { + define.apply(customElements, arguments); + shadowed.push(selector = is); + } + _whenDefined2(is).then(function () { + if (tag) { + _parse(document$1.querySelectorAll(selector)); + shadows.forEach(_parseShadow, [selector]); + } else parseShadowed(document$1.querySelectorAll(selector)); + }); + _defined.get(is)._(Class); + }; + } +})(); + +/***/ }), + +/***/ "./node_modules/an-array/index.js": +/*!****************************************!*\ + !*** ./node_modules/an-array/index.js ***! + \****************************************/ +/***/ ((module) => { + +var str = Object.prototype.toString; +module.exports = anArray; +function anArray(arr) { + return arr.BYTES_PER_ELEMENT && str.call(arr.buffer) === '[object ArrayBuffer]' || Array.isArray(arr); +} + +/***/ }), + +/***/ "./node_modules/as-number/index.js": +/*!*****************************************!*\ + !*** ./node_modules/as-number/index.js ***! + \*****************************************/ +/***/ ((module) => { + +module.exports = function numtype(num, def) { + return typeof num === 'number' ? num : typeof def === 'number' ? def : 0; +}; + +/***/ }), + +/***/ "./node_modules/base64-js/index.js": +/*!*****************************************!*\ + !*** ./node_modules/base64-js/index.js ***! + \*****************************************/ +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +exports.byteLength = byteLength; +exports.toByteArray = toByteArray; +exports.fromByteArray = fromByteArray; +var lookup = []; +var revLookup = []; +var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array; +var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; +for (var i = 0, len = code.length; i < len; ++i) { + lookup[i] = code[i]; + revLookup[code.charCodeAt(i)] = i; +} + +// Support decoding URL-safe base64 strings, as Node.js does. +// See: https://en.wikipedia.org/wiki/Base64#URL_applications +revLookup['-'.charCodeAt(0)] = 62; +revLookup['_'.charCodeAt(0)] = 63; +function getLens(b64) { + var len = b64.length; + if (len % 4 > 0) { + throw new Error('Invalid string. Length must be a multiple of 4'); + } + + // Trim off extra bytes after placeholder bytes are found + // See: https://github.com/beatgammit/base64-js/issues/42 + var validLen = b64.indexOf('='); + if (validLen === -1) validLen = len; + var placeHoldersLen = validLen === len ? 0 : 4 - validLen % 4; + return [validLen, placeHoldersLen]; +} + +// base64 is 4/3 + up to two characters of the original data +function byteLength(b64) { + var lens = getLens(b64); + var validLen = lens[0]; + var placeHoldersLen = lens[1]; + return (validLen + placeHoldersLen) * 3 / 4 - placeHoldersLen; +} +function _byteLength(b64, validLen, placeHoldersLen) { + return (validLen + placeHoldersLen) * 3 / 4 - placeHoldersLen; +} +function toByteArray(b64) { + var tmp; + var lens = getLens(b64); + var validLen = lens[0]; + var placeHoldersLen = lens[1]; + var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)); + var curByte = 0; + + // if there are placeholders, only get up to the last complete 4 chars + var len = placeHoldersLen > 0 ? validLen - 4 : validLen; + var i; + for (i = 0; i < len; i += 4) { + tmp = revLookup[b64.charCodeAt(i)] << 18 | revLookup[b64.charCodeAt(i + 1)] << 12 | revLookup[b64.charCodeAt(i + 2)] << 6 | revLookup[b64.charCodeAt(i + 3)]; + arr[curByte++] = tmp >> 16 & 0xFF; + arr[curByte++] = tmp >> 8 & 0xFF; + arr[curByte++] = tmp & 0xFF; + } + if (placeHoldersLen === 2) { + tmp = revLookup[b64.charCodeAt(i)] << 2 | revLookup[b64.charCodeAt(i + 1)] >> 4; + arr[curByte++] = tmp & 0xFF; + } + if (placeHoldersLen === 1) { + tmp = revLookup[b64.charCodeAt(i)] << 10 | revLookup[b64.charCodeAt(i + 1)] << 4 | revLookup[b64.charCodeAt(i + 2)] >> 2; + arr[curByte++] = tmp >> 8 & 0xFF; + arr[curByte++] = tmp & 0xFF; + } + return arr; +} +function tripletToBase64(num) { + return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]; +} +function encodeChunk(uint8, start, end) { + var tmp; + var output = []; + for (var i = start; i < end; i += 3) { + tmp = (uint8[i] << 16 & 0xFF0000) + (uint8[i + 1] << 8 & 0xFF00) + (uint8[i + 2] & 0xFF); + output.push(tripletToBase64(tmp)); + } + return output.join(''); +} +function fromByteArray(uint8) { + var tmp; + var len = uint8.length; + var extraBytes = len % 3; // if we have 1 byte left, pad 2 bytes + var parts = []; + var maxChunkLength = 16383; // must be multiple of 3 + + // go through the array every three bytes, we'll deal with trailing stuff later + for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { + parts.push(encodeChunk(uint8, i, i + maxChunkLength > len2 ? len2 : i + maxChunkLength)); + } + + // pad the end with zeros, but make sure to not forget the extra bytes + if (extraBytes === 1) { + tmp = uint8[len - 1]; + parts.push(lookup[tmp >> 2] + lookup[tmp << 4 & 0x3F] + '=='); + } else if (extraBytes === 2) { + tmp = (uint8[len - 2] << 8) + uint8[len - 1]; + parts.push(lookup[tmp >> 10] + lookup[tmp >> 4 & 0x3F] + lookup[tmp << 2 & 0x3F] + '='); + } + return parts.join(''); +} + +/***/ }), + +/***/ "./node_modules/buffer-equal/index.js": +/*!********************************************!*\ + !*** ./node_modules/buffer-equal/index.js ***! + \********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var Buffer = (__webpack_require__(/*! buffer */ "./node_modules/buffer/index.js").Buffer); // for use with browserify + +module.exports = function (a, b) { + if (!Buffer.isBuffer(a)) return undefined; + if (!Buffer.isBuffer(b)) return undefined; + if (typeof a.equals === 'function') return a.equals(b); + if (a.length !== b.length) return false; + for (var i = 0; i < a.length; i++) { + if (a[i] !== b[i]) return false; + } + return true; +}; + +/***/ }), + +/***/ "./node_modules/buffer/index.js": +/*!**************************************!*\ + !*** ./node_modules/buffer/index.js ***! + \**************************************/ +/***/ ((__unused_webpack_module, exports, __webpack_require__) => { + +"use strict"; +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ +/* eslint-disable no-proto */ + + + +const base64 = __webpack_require__(/*! base64-js */ "./node_modules/base64-js/index.js"); +const ieee754 = __webpack_require__(/*! ieee754 */ "./node_modules/ieee754/index.js"); +const customInspectSymbol = typeof Symbol === 'function' && typeof Symbol['for'] === 'function' // eslint-disable-line dot-notation +? Symbol['for']('nodejs.util.inspect.custom') // eslint-disable-line dot-notation +: null; +exports.Buffer = Buffer; +exports.SlowBuffer = SlowBuffer; +exports.INSPECT_MAX_BYTES = 50; +const K_MAX_LENGTH = 0x7fffffff; +exports.kMaxLength = K_MAX_LENGTH; + +/** + * If `Buffer.TYPED_ARRAY_SUPPORT`: + * === true Use Uint8Array implementation (fastest) + * === false Print warning and recommend using `buffer` v4.x which has an Object + * implementation (most compatible, even IE6) + * + * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, + * Opera 11.6+, iOS 4.2+. + * + * We report that the browser does not support typed arrays if the are not subclassable + * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array` + * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support + * for __proto__ and has a buggy typed array implementation. + */ +Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport(); +if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' && typeof console.error === 'function') { + console.error('This browser lacks typed array (Uint8Array) support which is required by ' + '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.'); +} +function typedArraySupport() { + // Can typed array instances can be augmented? + try { + const arr = new Uint8Array(1); + const proto = { + foo: function () { + return 42; + } + }; + Object.setPrototypeOf(proto, Uint8Array.prototype); + Object.setPrototypeOf(arr, proto); + return arr.foo() === 42; + } catch (e) { + return false; + } +} +Object.defineProperty(Buffer.prototype, 'parent', { + enumerable: true, + get: function () { + if (!Buffer.isBuffer(this)) return undefined; + return this.buffer; + } +}); +Object.defineProperty(Buffer.prototype, 'offset', { + enumerable: true, + get: function () { + if (!Buffer.isBuffer(this)) return undefined; + return this.byteOffset; + } +}); +function createBuffer(length) { + if (length > K_MAX_LENGTH) { + throw new RangeError('The value "' + length + '" is invalid for option "size"'); + } + // Return an augmented `Uint8Array` instance + const buf = new Uint8Array(length); + Object.setPrototypeOf(buf, Buffer.prototype); + return buf; +} + +/** + * The Buffer constructor returns instances of `Uint8Array` that have their + * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of + * `Uint8Array`, so the returned instances will have all the node `Buffer` methods + * and the `Uint8Array` methods. Square bracket notation works as expected -- it + * returns a single octet. + * + * The `Uint8Array` prototype remains unmodified. + */ + +function Buffer(arg, encodingOrOffset, length) { + // Common case. + if (typeof arg === 'number') { + if (typeof encodingOrOffset === 'string') { + throw new TypeError('The "string" argument must be of type string. Received type number'); + } + return allocUnsafe(arg); + } + return from(arg, encodingOrOffset, length); +} +Buffer.poolSize = 8192; // not used by this implementation + +function from(value, encodingOrOffset, length) { + if (typeof value === 'string') { + return fromString(value, encodingOrOffset); + } + if (ArrayBuffer.isView(value)) { + return fromArrayView(value); + } + if (value == null) { + throw new TypeError('The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + 'or Array-like Object. Received type ' + typeof value); + } + if (isInstance(value, ArrayBuffer) || value && isInstance(value.buffer, ArrayBuffer)) { + return fromArrayBuffer(value, encodingOrOffset, length); + } + if (typeof SharedArrayBuffer !== 'undefined' && (isInstance(value, SharedArrayBuffer) || value && isInstance(value.buffer, SharedArrayBuffer))) { + return fromArrayBuffer(value, encodingOrOffset, length); + } + if (typeof value === 'number') { + throw new TypeError('The "value" argument must not be of type number. Received type number'); + } + const valueOf = value.valueOf && value.valueOf(); + if (valueOf != null && valueOf !== value) { + return Buffer.from(valueOf, encodingOrOffset, length); + } + const b = fromObject(value); + if (b) return b; + if (typeof Symbol !== 'undefined' && Symbol.toPrimitive != null && typeof value[Symbol.toPrimitive] === 'function') { + return Buffer.from(value[Symbol.toPrimitive]('string'), encodingOrOffset, length); + } + throw new TypeError('The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + 'or Array-like Object. Received type ' + typeof value); +} + +/** + * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError + * if value is a number. + * Buffer.from(str[, encoding]) + * Buffer.from(array) + * Buffer.from(buffer) + * Buffer.from(arrayBuffer[, byteOffset[, length]]) + **/ +Buffer.from = function (value, encodingOrOffset, length) { + return from(value, encodingOrOffset, length); +}; + +// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug: +// https://github.com/feross/buffer/pull/148 +Object.setPrototypeOf(Buffer.prototype, Uint8Array.prototype); +Object.setPrototypeOf(Buffer, Uint8Array); +function assertSize(size) { + if (typeof size !== 'number') { + throw new TypeError('"size" argument must be of type number'); + } else if (size < 0) { + throw new RangeError('The value "' + size + '" is invalid for option "size"'); + } +} +function alloc(size, fill, encoding) { + assertSize(size); + if (size <= 0) { + return createBuffer(size); + } + if (fill !== undefined) { + // Only pay attention to encoding if it's a string. This + // prevents accidentally sending in a number that would + // be interpreted as a start offset. + return typeof encoding === 'string' ? createBuffer(size).fill(fill, encoding) : createBuffer(size).fill(fill); + } + return createBuffer(size); +} + +/** + * Creates a new filled Buffer instance. + * alloc(size[, fill[, encoding]]) + **/ +Buffer.alloc = function (size, fill, encoding) { + return alloc(size, fill, encoding); +}; +function allocUnsafe(size) { + assertSize(size); + return createBuffer(size < 0 ? 0 : checked(size) | 0); +} + +/** + * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. + * */ +Buffer.allocUnsafe = function (size) { + return allocUnsafe(size); +}; +/** + * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. + */ +Buffer.allocUnsafeSlow = function (size) { + return allocUnsafe(size); +}; +function fromString(string, encoding) { + if (typeof encoding !== 'string' || encoding === '') { + encoding = 'utf8'; + } + if (!Buffer.isEncoding(encoding)) { + throw new TypeError('Unknown encoding: ' + encoding); + } + const length = byteLength(string, encoding) | 0; + let buf = createBuffer(length); + const actual = buf.write(string, encoding); + if (actual !== length) { + // Writing a hex string, for example, that contains invalid characters will + // cause everything after the first invalid character to be ignored. (e.g. + // 'abxxcd' will be treated as 'ab') + buf = buf.slice(0, actual); + } + return buf; +} +function fromArrayLike(array) { + const length = array.length < 0 ? 0 : checked(array.length) | 0; + const buf = createBuffer(length); + for (let i = 0; i < length; i += 1) { + buf[i] = array[i] & 255; + } + return buf; +} +function fromArrayView(arrayView) { + if (isInstance(arrayView, Uint8Array)) { + const copy = new Uint8Array(arrayView); + return fromArrayBuffer(copy.buffer, copy.byteOffset, copy.byteLength); + } + return fromArrayLike(arrayView); +} +function fromArrayBuffer(array, byteOffset, length) { + if (byteOffset < 0 || array.byteLength < byteOffset) { + throw new RangeError('"offset" is outside of buffer bounds'); + } + if (array.byteLength < byteOffset + (length || 0)) { + throw new RangeError('"length" is outside of buffer bounds'); + } + let buf; + if (byteOffset === undefined && length === undefined) { + buf = new Uint8Array(array); + } else if (length === undefined) { + buf = new Uint8Array(array, byteOffset); + } else { + buf = new Uint8Array(array, byteOffset, length); + } + + // Return an augmented `Uint8Array` instance + Object.setPrototypeOf(buf, Buffer.prototype); + return buf; +} +function fromObject(obj) { + if (Buffer.isBuffer(obj)) { + const len = checked(obj.length) | 0; + const buf = createBuffer(len); + if (buf.length === 0) { + return buf; + } + obj.copy(buf, 0, 0, len); + return buf; + } + if (obj.length !== undefined) { + if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) { + return createBuffer(0); + } + return fromArrayLike(obj); + } + if (obj.type === 'Buffer' && Array.isArray(obj.data)) { + return fromArrayLike(obj.data); + } +} +function checked(length) { + // Note: cannot use `length < K_MAX_LENGTH` here because that fails when + // length is NaN (which is otherwise coerced to zero.) + if (length >= K_MAX_LENGTH) { + throw new RangeError('Attempt to allocate Buffer larger than maximum ' + 'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes'); + } + return length | 0; +} +function SlowBuffer(length) { + if (+length != length) { + // eslint-disable-line eqeqeq + length = 0; + } + return Buffer.alloc(+length); +} +Buffer.isBuffer = function isBuffer(b) { + return b != null && b._isBuffer === true && b !== Buffer.prototype; // so Buffer.isBuffer(Buffer.prototype) will be false +}; + +Buffer.compare = function compare(a, b) { + if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength); + if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength); + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + throw new TypeError('The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array'); + } + if (a === b) return 0; + let x = a.length; + let y = b.length; + for (let i = 0, len = Math.min(x, y); i < len; ++i) { + if (a[i] !== b[i]) { + x = a[i]; + y = b[i]; + break; + } + } + if (x < y) return -1; + if (y < x) return 1; + return 0; +}; +Buffer.isEncoding = function isEncoding(encoding) { + switch (String(encoding).toLowerCase()) { + case 'hex': + case 'utf8': + case 'utf-8': + case 'ascii': + case 'latin1': + case 'binary': + case 'base64': + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return true; + default: + return false; + } +}; +Buffer.concat = function concat(list, length) { + if (!Array.isArray(list)) { + throw new TypeError('"list" argument must be an Array of Buffers'); + } + if (list.length === 0) { + return Buffer.alloc(0); + } + let i; + if (length === undefined) { + length = 0; + for (i = 0; i < list.length; ++i) { + length += list[i].length; + } + } + const buffer = Buffer.allocUnsafe(length); + let pos = 0; + for (i = 0; i < list.length; ++i) { + let buf = list[i]; + if (isInstance(buf, Uint8Array)) { + if (pos + buf.length > buffer.length) { + if (!Buffer.isBuffer(buf)) buf = Buffer.from(buf); + buf.copy(buffer, pos); + } else { + Uint8Array.prototype.set.call(buffer, buf, pos); + } + } else if (!Buffer.isBuffer(buf)) { + throw new TypeError('"list" argument must be an Array of Buffers'); + } else { + buf.copy(buffer, pos); + } + pos += buf.length; + } + return buffer; +}; +function byteLength(string, encoding) { + if (Buffer.isBuffer(string)) { + return string.length; + } + if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) { + return string.byteLength; + } + if (typeof string !== 'string') { + throw new TypeError('The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' + 'Received type ' + typeof string); + } + const len = string.length; + const mustMatch = arguments.length > 2 && arguments[2] === true; + if (!mustMatch && len === 0) return 0; + + // Use a for loop to avoid recursion + let loweredCase = false; + for (;;) { + switch (encoding) { + case 'ascii': + case 'latin1': + case 'binary': + return len; + case 'utf8': + case 'utf-8': + return utf8ToBytes(string).length; + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return len * 2; + case 'hex': + return len >>> 1; + case 'base64': + return base64ToBytes(string).length; + default: + if (loweredCase) { + return mustMatch ? -1 : utf8ToBytes(string).length; // assume utf8 + } + + encoding = ('' + encoding).toLowerCase(); + loweredCase = true; + } + } +} +Buffer.byteLength = byteLength; +function slowToString(encoding, start, end) { + let loweredCase = false; + + // No need to verify that "this.length <= MAX_UINT32" since it's a read-only + // property of a typed array. + + // This behaves neither like String nor Uint8Array in that we set start/end + // to their upper/lower bounds if the value passed is out of range. + // undefined is handled specially as per ECMA-262 6th Edition, + // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. + if (start === undefined || start < 0) { + start = 0; + } + // Return early if start > this.length. Done here to prevent potential uint32 + // coercion fail below. + if (start > this.length) { + return ''; + } + if (end === undefined || end > this.length) { + end = this.length; + } + if (end <= 0) { + return ''; + } + + // Force coercion to uint32. This will also coerce falsey/NaN values to 0. + end >>>= 0; + start >>>= 0; + if (end <= start) { + return ''; + } + if (!encoding) encoding = 'utf8'; + while (true) { + switch (encoding) { + case 'hex': + return hexSlice(this, start, end); + case 'utf8': + case 'utf-8': + return utf8Slice(this, start, end); + case 'ascii': + return asciiSlice(this, start, end); + case 'latin1': + case 'binary': + return latin1Slice(this, start, end); + case 'base64': + return base64Slice(this, start, end); + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return utf16leSlice(this, start, end); + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding); + encoding = (encoding + '').toLowerCase(); + loweredCase = true; + } + } +} + +// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package) +// to detect a Buffer instance. It's not possible to use `instanceof Buffer` +// reliably in a browserify context because there could be multiple different +// copies of the 'buffer' package in use. This method works even for Buffer +// instances that were created from another copy of the `buffer` package. +// See: https://github.com/feross/buffer/issues/154 +Buffer.prototype._isBuffer = true; +function swap(b, n, m) { + const i = b[n]; + b[n] = b[m]; + b[m] = i; +} +Buffer.prototype.swap16 = function swap16() { + const len = this.length; + if (len % 2 !== 0) { + throw new RangeError('Buffer size must be a multiple of 16-bits'); + } + for (let i = 0; i < len; i += 2) { + swap(this, i, i + 1); + } + return this; +}; +Buffer.prototype.swap32 = function swap32() { + const len = this.length; + if (len % 4 !== 0) { + throw new RangeError('Buffer size must be a multiple of 32-bits'); + } + for (let i = 0; i < len; i += 4) { + swap(this, i, i + 3); + swap(this, i + 1, i + 2); + } + return this; +}; +Buffer.prototype.swap64 = function swap64() { + const len = this.length; + if (len % 8 !== 0) { + throw new RangeError('Buffer size must be a multiple of 64-bits'); + } + for (let i = 0; i < len; i += 8) { + swap(this, i, i + 7); + swap(this, i + 1, i + 6); + swap(this, i + 2, i + 5); + swap(this, i + 3, i + 4); + } + return this; +}; +Buffer.prototype.toString = function toString() { + const length = this.length; + if (length === 0) return ''; + if (arguments.length === 0) return utf8Slice(this, 0, length); + return slowToString.apply(this, arguments); +}; +Buffer.prototype.toLocaleString = Buffer.prototype.toString; +Buffer.prototype.equals = function equals(b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer'); + if (this === b) return true; + return Buffer.compare(this, b) === 0; +}; +Buffer.prototype.inspect = function inspect() { + let str = ''; + const max = exports.INSPECT_MAX_BYTES; + str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim(); + if (this.length > max) str += ' ... '; + return ''; +}; +if (customInspectSymbol) { + Buffer.prototype[customInspectSymbol] = Buffer.prototype.inspect; +} +Buffer.prototype.compare = function compare(target, start, end, thisStart, thisEnd) { + if (isInstance(target, Uint8Array)) { + target = Buffer.from(target, target.offset, target.byteLength); + } + if (!Buffer.isBuffer(target)) { + throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. ' + 'Received type ' + typeof target); + } + if (start === undefined) { + start = 0; + } + if (end === undefined) { + end = target ? target.length : 0; + } + if (thisStart === undefined) { + thisStart = 0; + } + if (thisEnd === undefined) { + thisEnd = this.length; + } + if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { + throw new RangeError('out of range index'); + } + if (thisStart >= thisEnd && start >= end) { + return 0; + } + if (thisStart >= thisEnd) { + return -1; + } + if (start >= end) { + return 1; + } + start >>>= 0; + end >>>= 0; + thisStart >>>= 0; + thisEnd >>>= 0; + if (this === target) return 0; + let x = thisEnd - thisStart; + let y = end - start; + const len = Math.min(x, y); + const thisCopy = this.slice(thisStart, thisEnd); + const targetCopy = target.slice(start, end); + for (let i = 0; i < len; ++i) { + if (thisCopy[i] !== targetCopy[i]) { + x = thisCopy[i]; + y = targetCopy[i]; + break; + } + } + if (x < y) return -1; + if (y < x) return 1; + return 0; +}; + +// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, +// OR the last index of `val` in `buffer` at offset <= `byteOffset`. +// +// Arguments: +// - buffer - a Buffer to search +// - val - a string, Buffer, or number +// - byteOffset - an index into `buffer`; will be clamped to an int32 +// - encoding - an optional encoding, relevant is val is a string +// - dir - true for indexOf, false for lastIndexOf +function bidirectionalIndexOf(buffer, val, byteOffset, encoding, dir) { + // Empty buffer means no match + if (buffer.length === 0) return -1; + + // Normalize byteOffset + if (typeof byteOffset === 'string') { + encoding = byteOffset; + byteOffset = 0; + } else if (byteOffset > 0x7fffffff) { + byteOffset = 0x7fffffff; + } else if (byteOffset < -0x80000000) { + byteOffset = -0x80000000; + } + byteOffset = +byteOffset; // Coerce to Number. + if (numberIsNaN(byteOffset)) { + // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer + byteOffset = dir ? 0 : buffer.length - 1; + } + + // Normalize byteOffset: negative offsets start from the end of the buffer + if (byteOffset < 0) byteOffset = buffer.length + byteOffset; + if (byteOffset >= buffer.length) { + if (dir) return -1;else byteOffset = buffer.length - 1; + } else if (byteOffset < 0) { + if (dir) byteOffset = 0;else return -1; + } + + // Normalize val + if (typeof val === 'string') { + val = Buffer.from(val, encoding); + } + + // Finally, search either indexOf (if dir is true) or lastIndexOf + if (Buffer.isBuffer(val)) { + // Special case: looking for empty string/buffer always fails + if (val.length === 0) { + return -1; + } + return arrayIndexOf(buffer, val, byteOffset, encoding, dir); + } else if (typeof val === 'number') { + val = val & 0xFF; // Search for a byte value [0-255] + if (typeof Uint8Array.prototype.indexOf === 'function') { + if (dir) { + return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset); + } else { + return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset); + } + } + return arrayIndexOf(buffer, [val], byteOffset, encoding, dir); + } + throw new TypeError('val must be string, number or Buffer'); +} +function arrayIndexOf(arr, val, byteOffset, encoding, dir) { + let indexSize = 1; + let arrLength = arr.length; + let valLength = val.length; + if (encoding !== undefined) { + encoding = String(encoding).toLowerCase(); + if (encoding === 'ucs2' || encoding === 'ucs-2' || encoding === 'utf16le' || encoding === 'utf-16le') { + if (arr.length < 2 || val.length < 2) { + return -1; + } + indexSize = 2; + arrLength /= 2; + valLength /= 2; + byteOffset /= 2; + } + } + function read(buf, i) { + if (indexSize === 1) { + return buf[i]; + } else { + return buf.readUInt16BE(i * indexSize); + } + } + let i; + if (dir) { + let foundIndex = -1; + for (i = byteOffset; i < arrLength; i++) { + if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { + if (foundIndex === -1) foundIndex = i; + if (i - foundIndex + 1 === valLength) return foundIndex * indexSize; + } else { + if (foundIndex !== -1) i -= i - foundIndex; + foundIndex = -1; + } + } + } else { + if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength; + for (i = byteOffset; i >= 0; i--) { + let found = true; + for (let j = 0; j < valLength; j++) { + if (read(arr, i + j) !== read(val, j)) { + found = false; + break; + } + } + if (found) return i; + } + } + return -1; +} +Buffer.prototype.includes = function includes(val, byteOffset, encoding) { + return this.indexOf(val, byteOffset, encoding) !== -1; +}; +Buffer.prototype.indexOf = function indexOf(val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, true); +}; +Buffer.prototype.lastIndexOf = function lastIndexOf(val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, false); +}; +function hexWrite(buf, string, offset, length) { + offset = Number(offset) || 0; + const remaining = buf.length - offset; + if (!length) { + length = remaining; + } else { + length = Number(length); + if (length > remaining) { + length = remaining; + } + } + const strLen = string.length; + if (length > strLen / 2) { + length = strLen / 2; + } + let i; + for (i = 0; i < length; ++i) { + const parsed = parseInt(string.substr(i * 2, 2), 16); + if (numberIsNaN(parsed)) return i; + buf[offset + i] = parsed; + } + return i; +} +function utf8Write(buf, string, offset, length) { + return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length); +} +function asciiWrite(buf, string, offset, length) { + return blitBuffer(asciiToBytes(string), buf, offset, length); +} +function base64Write(buf, string, offset, length) { + return blitBuffer(base64ToBytes(string), buf, offset, length); +} +function ucs2Write(buf, string, offset, length) { + return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length); +} +Buffer.prototype.write = function write(string, offset, length, encoding) { + // Buffer#write(string) + if (offset === undefined) { + encoding = 'utf8'; + length = this.length; + offset = 0; + // Buffer#write(string, encoding) + } else if (length === undefined && typeof offset === 'string') { + encoding = offset; + length = this.length; + offset = 0; + // Buffer#write(string, offset[, length][, encoding]) + } else if (isFinite(offset)) { + offset = offset >>> 0; + if (isFinite(length)) { + length = length >>> 0; + if (encoding === undefined) encoding = 'utf8'; + } else { + encoding = length; + length = undefined; + } + } else { + throw new Error('Buffer.write(string, encoding, offset[, length]) is no longer supported'); + } + const remaining = this.length - offset; + if (length === undefined || length > remaining) length = remaining; + if (string.length > 0 && (length < 0 || offset < 0) || offset > this.length) { + throw new RangeError('Attempt to write outside buffer bounds'); + } + if (!encoding) encoding = 'utf8'; + let loweredCase = false; + for (;;) { + switch (encoding) { + case 'hex': + return hexWrite(this, string, offset, length); + case 'utf8': + case 'utf-8': + return utf8Write(this, string, offset, length); + case 'ascii': + case 'latin1': + case 'binary': + return asciiWrite(this, string, offset, length); + case 'base64': + // Warning: maxLength not taken into account in base64Write + return base64Write(this, string, offset, length); + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return ucs2Write(this, string, offset, length); + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding); + encoding = ('' + encoding).toLowerCase(); + loweredCase = true; + } + } +}; +Buffer.prototype.toJSON = function toJSON() { + return { + type: 'Buffer', + data: Array.prototype.slice.call(this._arr || this, 0) + }; +}; +function base64Slice(buf, start, end) { + if (start === 0 && end === buf.length) { + return base64.fromByteArray(buf); + } else { + return base64.fromByteArray(buf.slice(start, end)); + } +} +function utf8Slice(buf, start, end) { + end = Math.min(buf.length, end); + const res = []; + let i = start; + while (i < end) { + const firstByte = buf[i]; + let codePoint = null; + let bytesPerSequence = firstByte > 0xEF ? 4 : firstByte > 0xDF ? 3 : firstByte > 0xBF ? 2 : 1; + if (i + bytesPerSequence <= end) { + let secondByte, thirdByte, fourthByte, tempCodePoint; + switch (bytesPerSequence) { + case 1: + if (firstByte < 0x80) { + codePoint = firstByte; + } + break; + case 2: + secondByte = buf[i + 1]; + if ((secondByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0x1F) << 0x6 | secondByte & 0x3F; + if (tempCodePoint > 0x7F) { + codePoint = tempCodePoint; + } + } + break; + case 3: + secondByte = buf[i + 1]; + thirdByte = buf[i + 2]; + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | thirdByte & 0x3F; + if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { + codePoint = tempCodePoint; + } + } + break; + case 4: + secondByte = buf[i + 1]; + thirdByte = buf[i + 2]; + fourthByte = buf[i + 3]; + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | fourthByte & 0x3F; + if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { + codePoint = tempCodePoint; + } + } + } + } + if (codePoint === null) { + // we did not generate a valid codePoint so insert a + // replacement char (U+FFFD) and advance only 1 byte + codePoint = 0xFFFD; + bytesPerSequence = 1; + } else if (codePoint > 0xFFFF) { + // encode to utf16 (surrogate pair dance) + codePoint -= 0x10000; + res.push(codePoint >>> 10 & 0x3FF | 0xD800); + codePoint = 0xDC00 | codePoint & 0x3FF; + } + res.push(codePoint); + i += bytesPerSequence; + } + return decodeCodePointsArray(res); +} + +// Based on http://stackoverflow.com/a/22747272/680742, the browser with +// the lowest limit is Chrome, with 0x10000 args. +// We go 1 magnitude less, for safety +const MAX_ARGUMENTS_LENGTH = 0x1000; +function decodeCodePointsArray(codePoints) { + const len = codePoints.length; + if (len <= MAX_ARGUMENTS_LENGTH) { + return String.fromCharCode.apply(String, codePoints); // avoid extra slice() + } + + // Decode in chunks to avoid "call stack size exceeded". + let res = ''; + let i = 0; + while (i < len) { + res += String.fromCharCode.apply(String, codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)); + } + return res; +} +function asciiSlice(buf, start, end) { + let ret = ''; + end = Math.min(buf.length, end); + for (let i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i] & 0x7F); + } + return ret; +} +function latin1Slice(buf, start, end) { + let ret = ''; + end = Math.min(buf.length, end); + for (let i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i]); + } + return ret; +} +function hexSlice(buf, start, end) { + const len = buf.length; + if (!start || start < 0) start = 0; + if (!end || end < 0 || end > len) end = len; + let out = ''; + for (let i = start; i < end; ++i) { + out += hexSliceLookupTable[buf[i]]; + } + return out; +} +function utf16leSlice(buf, start, end) { + const bytes = buf.slice(start, end); + let res = ''; + // If bytes.length is odd, the last 8 bits must be ignored (same as node.js) + for (let i = 0; i < bytes.length - 1; i += 2) { + res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256); + } + return res; +} +Buffer.prototype.slice = function slice(start, end) { + const len = this.length; + start = ~~start; + end = end === undefined ? len : ~~end; + if (start < 0) { + start += len; + if (start < 0) start = 0; + } else if (start > len) { + start = len; + } + if (end < 0) { + end += len; + if (end < 0) end = 0; + } else if (end > len) { + end = len; + } + if (end < start) end = start; + const newBuf = this.subarray(start, end); + // Return an augmented `Uint8Array` instance + Object.setPrototypeOf(newBuf, Buffer.prototype); + return newBuf; +}; + +/* + * Need to make sure that buffer isn't trying to write out of bounds. + */ +function checkOffset(offset, ext, length) { + if (offset % 1 !== 0 || offset < 0) throw new RangeError('offset is not uint'); + if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length'); +} +Buffer.prototype.readUintLE = Buffer.prototype.readUIntLE = function readUIntLE(offset, byteLength, noAssert) { + offset = offset >>> 0; + byteLength = byteLength >>> 0; + if (!noAssert) checkOffset(offset, byteLength, this.length); + let val = this[offset]; + let mul = 1; + let i = 0; + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul; + } + return val; +}; +Buffer.prototype.readUintBE = Buffer.prototype.readUIntBE = function readUIntBE(offset, byteLength, noAssert) { + offset = offset >>> 0; + byteLength = byteLength >>> 0; + if (!noAssert) { + checkOffset(offset, byteLength, this.length); + } + let val = this[offset + --byteLength]; + let mul = 1; + while (byteLength > 0 && (mul *= 0x100)) { + val += this[offset + --byteLength] * mul; + } + return val; +}; +Buffer.prototype.readUint8 = Buffer.prototype.readUInt8 = function readUInt8(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 1, this.length); + return this[offset]; +}; +Buffer.prototype.readUint16LE = Buffer.prototype.readUInt16LE = function readUInt16LE(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 2, this.length); + return this[offset] | this[offset + 1] << 8; +}; +Buffer.prototype.readUint16BE = Buffer.prototype.readUInt16BE = function readUInt16BE(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 2, this.length); + return this[offset] << 8 | this[offset + 1]; +}; +Buffer.prototype.readUint32LE = Buffer.prototype.readUInt32LE = function readUInt32LE(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 4, this.length); + return (this[offset] | this[offset + 1] << 8 | this[offset + 2] << 16) + this[offset + 3] * 0x1000000; +}; +Buffer.prototype.readUint32BE = Buffer.prototype.readUInt32BE = function readUInt32BE(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 4, this.length); + return this[offset] * 0x1000000 + (this[offset + 1] << 16 | this[offset + 2] << 8 | this[offset + 3]); +}; +Buffer.prototype.readBigUInt64LE = defineBigIntMethod(function readBigUInt64LE(offset) { + offset = offset >>> 0; + validateNumber(offset, 'offset'); + const first = this[offset]; + const last = this[offset + 7]; + if (first === undefined || last === undefined) { + boundsError(offset, this.length - 8); + } + const lo = first + this[++offset] * 2 ** 8 + this[++offset] * 2 ** 16 + this[++offset] * 2 ** 24; + const hi = this[++offset] + this[++offset] * 2 ** 8 + this[++offset] * 2 ** 16 + last * 2 ** 24; + return BigInt(lo) + (BigInt(hi) << BigInt(32)); +}); +Buffer.prototype.readBigUInt64BE = defineBigIntMethod(function readBigUInt64BE(offset) { + offset = offset >>> 0; + validateNumber(offset, 'offset'); + const first = this[offset]; + const last = this[offset + 7]; + if (first === undefined || last === undefined) { + boundsError(offset, this.length - 8); + } + const hi = first * 2 ** 24 + this[++offset] * 2 ** 16 + this[++offset] * 2 ** 8 + this[++offset]; + const lo = this[++offset] * 2 ** 24 + this[++offset] * 2 ** 16 + this[++offset] * 2 ** 8 + last; + return (BigInt(hi) << BigInt(32)) + BigInt(lo); +}); +Buffer.prototype.readIntLE = function readIntLE(offset, byteLength, noAssert) { + offset = offset >>> 0; + byteLength = byteLength >>> 0; + if (!noAssert) checkOffset(offset, byteLength, this.length); + let val = this[offset]; + let mul = 1; + let i = 0; + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul; + } + mul *= 0x80; + if (val >= mul) val -= Math.pow(2, 8 * byteLength); + return val; +}; +Buffer.prototype.readIntBE = function readIntBE(offset, byteLength, noAssert) { + offset = offset >>> 0; + byteLength = byteLength >>> 0; + if (!noAssert) checkOffset(offset, byteLength, this.length); + let i = byteLength; + let mul = 1; + let val = this[offset + --i]; + while (i > 0 && (mul *= 0x100)) { + val += this[offset + --i] * mul; + } + mul *= 0x80; + if (val >= mul) val -= Math.pow(2, 8 * byteLength); + return val; +}; +Buffer.prototype.readInt8 = function readInt8(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 1, this.length); + if (!(this[offset] & 0x80)) return this[offset]; + return (0xff - this[offset] + 1) * -1; +}; +Buffer.prototype.readInt16LE = function readInt16LE(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 2, this.length); + const val = this[offset] | this[offset + 1] << 8; + return val & 0x8000 ? val | 0xFFFF0000 : val; +}; +Buffer.prototype.readInt16BE = function readInt16BE(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 2, this.length); + const val = this[offset + 1] | this[offset] << 8; + return val & 0x8000 ? val | 0xFFFF0000 : val; +}; +Buffer.prototype.readInt32LE = function readInt32LE(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 4, this.length); + return this[offset] | this[offset + 1] << 8 | this[offset + 2] << 16 | this[offset + 3] << 24; +}; +Buffer.prototype.readInt32BE = function readInt32BE(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 4, this.length); + return this[offset] << 24 | this[offset + 1] << 16 | this[offset + 2] << 8 | this[offset + 3]; +}; +Buffer.prototype.readBigInt64LE = defineBigIntMethod(function readBigInt64LE(offset) { + offset = offset >>> 0; + validateNumber(offset, 'offset'); + const first = this[offset]; + const last = this[offset + 7]; + if (first === undefined || last === undefined) { + boundsError(offset, this.length - 8); + } + const val = this[offset + 4] + this[offset + 5] * 2 ** 8 + this[offset + 6] * 2 ** 16 + (last << 24); // Overflow + + return (BigInt(val) << BigInt(32)) + BigInt(first + this[++offset] * 2 ** 8 + this[++offset] * 2 ** 16 + this[++offset] * 2 ** 24); +}); +Buffer.prototype.readBigInt64BE = defineBigIntMethod(function readBigInt64BE(offset) { + offset = offset >>> 0; + validateNumber(offset, 'offset'); + const first = this[offset]; + const last = this[offset + 7]; + if (first === undefined || last === undefined) { + boundsError(offset, this.length - 8); + } + const val = (first << 24) + + // Overflow + this[++offset] * 2 ** 16 + this[++offset] * 2 ** 8 + this[++offset]; + return (BigInt(val) << BigInt(32)) + BigInt(this[++offset] * 2 ** 24 + this[++offset] * 2 ** 16 + this[++offset] * 2 ** 8 + last); +}); +Buffer.prototype.readFloatLE = function readFloatLE(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 4, this.length); + return ieee754.read(this, offset, true, 23, 4); +}; +Buffer.prototype.readFloatBE = function readFloatBE(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 4, this.length); + return ieee754.read(this, offset, false, 23, 4); +}; +Buffer.prototype.readDoubleLE = function readDoubleLE(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 8, this.length); + return ieee754.read(this, offset, true, 52, 8); +}; +Buffer.prototype.readDoubleBE = function readDoubleBE(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 8, this.length); + return ieee754.read(this, offset, false, 52, 8); +}; +function checkInt(buf, value, offset, ext, max, min) { + if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance'); + if (value > max || value < min) throw new RangeError('"value" argument is out of bounds'); + if (offset + ext > buf.length) throw new RangeError('Index out of range'); +} +Buffer.prototype.writeUintLE = Buffer.prototype.writeUIntLE = function writeUIntLE(value, offset, byteLength, noAssert) { + value = +value; + offset = offset >>> 0; + byteLength = byteLength >>> 0; + if (!noAssert) { + const maxBytes = Math.pow(2, 8 * byteLength) - 1; + checkInt(this, value, offset, byteLength, maxBytes, 0); + } + let mul = 1; + let i = 0; + this[offset] = value & 0xFF; + while (++i < byteLength && (mul *= 0x100)) { + this[offset + i] = value / mul & 0xFF; + } + return offset + byteLength; +}; +Buffer.prototype.writeUintBE = Buffer.prototype.writeUIntBE = function writeUIntBE(value, offset, byteLength, noAssert) { + value = +value; + offset = offset >>> 0; + byteLength = byteLength >>> 0; + if (!noAssert) { + const maxBytes = Math.pow(2, 8 * byteLength) - 1; + checkInt(this, value, offset, byteLength, maxBytes, 0); + } + let i = byteLength - 1; + let mul = 1; + this[offset + i] = value & 0xFF; + while (--i >= 0 && (mul *= 0x100)) { + this[offset + i] = value / mul & 0xFF; + } + return offset + byteLength; +}; +Buffer.prototype.writeUint8 = Buffer.prototype.writeUInt8 = function writeUInt8(value, offset, noAssert) { + value = +value; + offset = offset >>> 0; + if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0); + this[offset] = value & 0xff; + return offset + 1; +}; +Buffer.prototype.writeUint16LE = Buffer.prototype.writeUInt16LE = function writeUInt16LE(value, offset, noAssert) { + value = +value; + offset = offset >>> 0; + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0); + this[offset] = value & 0xff; + this[offset + 1] = value >>> 8; + return offset + 2; +}; +Buffer.prototype.writeUint16BE = Buffer.prototype.writeUInt16BE = function writeUInt16BE(value, offset, noAssert) { + value = +value; + offset = offset >>> 0; + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0); + this[offset] = value >>> 8; + this[offset + 1] = value & 0xff; + return offset + 2; +}; +Buffer.prototype.writeUint32LE = Buffer.prototype.writeUInt32LE = function writeUInt32LE(value, offset, noAssert) { + value = +value; + offset = offset >>> 0; + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0); + this[offset + 3] = value >>> 24; + this[offset + 2] = value >>> 16; + this[offset + 1] = value >>> 8; + this[offset] = value & 0xff; + return offset + 4; +}; +Buffer.prototype.writeUint32BE = Buffer.prototype.writeUInt32BE = function writeUInt32BE(value, offset, noAssert) { + value = +value; + offset = offset >>> 0; + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0); + this[offset] = value >>> 24; + this[offset + 1] = value >>> 16; + this[offset + 2] = value >>> 8; + this[offset + 3] = value & 0xff; + return offset + 4; +}; +function wrtBigUInt64LE(buf, value, offset, min, max) { + checkIntBI(value, min, max, buf, offset, 7); + let lo = Number(value & BigInt(0xffffffff)); + buf[offset++] = lo; + lo = lo >> 8; + buf[offset++] = lo; + lo = lo >> 8; + buf[offset++] = lo; + lo = lo >> 8; + buf[offset++] = lo; + let hi = Number(value >> BigInt(32) & BigInt(0xffffffff)); + buf[offset++] = hi; + hi = hi >> 8; + buf[offset++] = hi; + hi = hi >> 8; + buf[offset++] = hi; + hi = hi >> 8; + buf[offset++] = hi; + return offset; +} +function wrtBigUInt64BE(buf, value, offset, min, max) { + checkIntBI(value, min, max, buf, offset, 7); + let lo = Number(value & BigInt(0xffffffff)); + buf[offset + 7] = lo; + lo = lo >> 8; + buf[offset + 6] = lo; + lo = lo >> 8; + buf[offset + 5] = lo; + lo = lo >> 8; + buf[offset + 4] = lo; + let hi = Number(value >> BigInt(32) & BigInt(0xffffffff)); + buf[offset + 3] = hi; + hi = hi >> 8; + buf[offset + 2] = hi; + hi = hi >> 8; + buf[offset + 1] = hi; + hi = hi >> 8; + buf[offset] = hi; + return offset + 8; +} +Buffer.prototype.writeBigUInt64LE = defineBigIntMethod(function writeBigUInt64LE(value, offset = 0) { + return wrtBigUInt64LE(this, value, offset, BigInt(0), BigInt('0xffffffffffffffff')); +}); +Buffer.prototype.writeBigUInt64BE = defineBigIntMethod(function writeBigUInt64BE(value, offset = 0) { + return wrtBigUInt64BE(this, value, offset, BigInt(0), BigInt('0xffffffffffffffff')); +}); +Buffer.prototype.writeIntLE = function writeIntLE(value, offset, byteLength, noAssert) { + value = +value; + offset = offset >>> 0; + if (!noAssert) { + const limit = Math.pow(2, 8 * byteLength - 1); + checkInt(this, value, offset, byteLength, limit - 1, -limit); + } + let i = 0; + let mul = 1; + let sub = 0; + this[offset] = value & 0xFF; + while (++i < byteLength && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { + sub = 1; + } + this[offset + i] = (value / mul >> 0) - sub & 0xFF; + } + return offset + byteLength; +}; +Buffer.prototype.writeIntBE = function writeIntBE(value, offset, byteLength, noAssert) { + value = +value; + offset = offset >>> 0; + if (!noAssert) { + const limit = Math.pow(2, 8 * byteLength - 1); + checkInt(this, value, offset, byteLength, limit - 1, -limit); + } + let i = byteLength - 1; + let mul = 1; + let sub = 0; + this[offset + i] = value & 0xFF; + while (--i >= 0 && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { + sub = 1; + } + this[offset + i] = (value / mul >> 0) - sub & 0xFF; + } + return offset + byteLength; +}; +Buffer.prototype.writeInt8 = function writeInt8(value, offset, noAssert) { + value = +value; + offset = offset >>> 0; + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (value < 0) value = 0xff + value + 1; + this[offset] = value & 0xff; + return offset + 1; +}; +Buffer.prototype.writeInt16LE = function writeInt16LE(value, offset, noAssert) { + value = +value; + offset = offset >>> 0; + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + this[offset] = value & 0xff; + this[offset + 1] = value >>> 8; + return offset + 2; +}; +Buffer.prototype.writeInt16BE = function writeInt16BE(value, offset, noAssert) { + value = +value; + offset = offset >>> 0; + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + this[offset] = value >>> 8; + this[offset + 1] = value & 0xff; + return offset + 2; +}; +Buffer.prototype.writeInt32LE = function writeInt32LE(value, offset, noAssert) { + value = +value; + offset = offset >>> 0; + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + this[offset] = value & 0xff; + this[offset + 1] = value >>> 8; + this[offset + 2] = value >>> 16; + this[offset + 3] = value >>> 24; + return offset + 4; +}; +Buffer.prototype.writeInt32BE = function writeInt32BE(value, offset, noAssert) { + value = +value; + offset = offset >>> 0; + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (value < 0) value = 0xffffffff + value + 1; + this[offset] = value >>> 24; + this[offset + 1] = value >>> 16; + this[offset + 2] = value >>> 8; + this[offset + 3] = value & 0xff; + return offset + 4; +}; +Buffer.prototype.writeBigInt64LE = defineBigIntMethod(function writeBigInt64LE(value, offset = 0) { + return wrtBigUInt64LE(this, value, offset, -BigInt('0x8000000000000000'), BigInt('0x7fffffffffffffff')); +}); +Buffer.prototype.writeBigInt64BE = defineBigIntMethod(function writeBigInt64BE(value, offset = 0) { + return wrtBigUInt64BE(this, value, offset, -BigInt('0x8000000000000000'), BigInt('0x7fffffffffffffff')); +}); +function checkIEEE754(buf, value, offset, ext, max, min) { + if (offset + ext > buf.length) throw new RangeError('Index out of range'); + if (offset < 0) throw new RangeError('Index out of range'); +} +function writeFloat(buf, value, offset, littleEndian, noAssert) { + value = +value; + offset = offset >>> 0; + if (!noAssert) { + checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38); + } + ieee754.write(buf, value, offset, littleEndian, 23, 4); + return offset + 4; +} +Buffer.prototype.writeFloatLE = function writeFloatLE(value, offset, noAssert) { + return writeFloat(this, value, offset, true, noAssert); +}; +Buffer.prototype.writeFloatBE = function writeFloatBE(value, offset, noAssert) { + return writeFloat(this, value, offset, false, noAssert); +}; +function writeDouble(buf, value, offset, littleEndian, noAssert) { + value = +value; + offset = offset >>> 0; + if (!noAssert) { + checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308); + } + ieee754.write(buf, value, offset, littleEndian, 52, 8); + return offset + 8; +} +Buffer.prototype.writeDoubleLE = function writeDoubleLE(value, offset, noAssert) { + return writeDouble(this, value, offset, true, noAssert); +}; +Buffer.prototype.writeDoubleBE = function writeDoubleBE(value, offset, noAssert) { + return writeDouble(this, value, offset, false, noAssert); +}; + +// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) +Buffer.prototype.copy = function copy(target, targetStart, start, end) { + if (!Buffer.isBuffer(target)) throw new TypeError('argument should be a Buffer'); + if (!start) start = 0; + if (!end && end !== 0) end = this.length; + if (targetStart >= target.length) targetStart = target.length; + if (!targetStart) targetStart = 0; + if (end > 0 && end < start) end = start; + + // Copy 0 bytes; we're done + if (end === start) return 0; + if (target.length === 0 || this.length === 0) return 0; + + // Fatal error conditions + if (targetStart < 0) { + throw new RangeError('targetStart out of bounds'); + } + if (start < 0 || start >= this.length) throw new RangeError('Index out of range'); + if (end < 0) throw new RangeError('sourceEnd out of bounds'); + + // Are we oob? + if (end > this.length) end = this.length; + if (target.length - targetStart < end - start) { + end = target.length - targetStart + start; + } + const len = end - start; + if (this === target && typeof Uint8Array.prototype.copyWithin === 'function') { + // Use built-in when available, missing from IE11 + this.copyWithin(targetStart, start, end); + } else { + Uint8Array.prototype.set.call(target, this.subarray(start, end), targetStart); + } + return len; +}; + +// Usage: +// buffer.fill(number[, offset[, end]]) +// buffer.fill(buffer[, offset[, end]]) +// buffer.fill(string[, offset[, end]][, encoding]) +Buffer.prototype.fill = function fill(val, start, end, encoding) { + // Handle string cases: + if (typeof val === 'string') { + if (typeof start === 'string') { + encoding = start; + start = 0; + end = this.length; + } else if (typeof end === 'string') { + encoding = end; + end = this.length; + } + if (encoding !== undefined && typeof encoding !== 'string') { + throw new TypeError('encoding must be a string'); + } + if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { + throw new TypeError('Unknown encoding: ' + encoding); + } + if (val.length === 1) { + const code = val.charCodeAt(0); + if (encoding === 'utf8' && code < 128 || encoding === 'latin1') { + // Fast path: If `val` fits into a single byte, use that numeric value. + val = code; + } + } + } else if (typeof val === 'number') { + val = val & 255; + } else if (typeof val === 'boolean') { + val = Number(val); + } + + // Invalid ranges are not set to a default, so can range check early. + if (start < 0 || this.length < start || this.length < end) { + throw new RangeError('Out of range index'); + } + if (end <= start) { + return this; + } + start = start >>> 0; + end = end === undefined ? this.length : end >>> 0; + if (!val) val = 0; + let i; + if (typeof val === 'number') { + for (i = start; i < end; ++i) { + this[i] = val; + } + } else { + const bytes = Buffer.isBuffer(val) ? val : Buffer.from(val, encoding); + const len = bytes.length; + if (len === 0) { + throw new TypeError('The value "' + val + '" is invalid for argument "value"'); + } + for (i = 0; i < end - start; ++i) { + this[i + start] = bytes[i % len]; + } + } + return this; +}; + +// CUSTOM ERRORS +// ============= + +// Simplified versions from Node, changed for Buffer-only usage +const errors = {}; +function E(sym, getMessage, Base) { + errors[sym] = class NodeError extends Base { + constructor() { + super(); + Object.defineProperty(this, 'message', { + value: getMessage.apply(this, arguments), + writable: true, + configurable: true + }); + + // Add the error code to the name to include it in the stack trace. + this.name = `${this.name} [${sym}]`; + // Access the stack to generate the error message including the error code + // from the name. + this.stack; // eslint-disable-line no-unused-expressions + // Reset the name to the actual name. + delete this.name; + } + get code() { + return sym; + } + set code(value) { + Object.defineProperty(this, 'code', { + configurable: true, + enumerable: true, + value, + writable: true + }); + } + toString() { + return `${this.name} [${sym}]: ${this.message}`; + } + }; +} +E('ERR_BUFFER_OUT_OF_BOUNDS', function (name) { + if (name) { + return `${name} is outside of buffer bounds`; + } + return 'Attempt to access memory outside buffer bounds'; +}, RangeError); +E('ERR_INVALID_ARG_TYPE', function (name, actual) { + return `The "${name}" argument must be of type number. Received type ${typeof actual}`; +}, TypeError); +E('ERR_OUT_OF_RANGE', function (str, range, input) { + let msg = `The value of "${str}" is out of range.`; + let received = input; + if (Number.isInteger(input) && Math.abs(input) > 2 ** 32) { + received = addNumericalSeparator(String(input)); + } else if (typeof input === 'bigint') { + received = String(input); + if (input > BigInt(2) ** BigInt(32) || input < -(BigInt(2) ** BigInt(32))) { + received = addNumericalSeparator(received); + } + received += 'n'; + } + msg += ` It must be ${range}. Received ${received}`; + return msg; +}, RangeError); +function addNumericalSeparator(val) { + let res = ''; + let i = val.length; + const start = val[0] === '-' ? 1 : 0; + for (; i >= start + 4; i -= 3) { + res = `_${val.slice(i - 3, i)}${res}`; + } + return `${val.slice(0, i)}${res}`; +} + +// CHECK FUNCTIONS +// =============== + +function checkBounds(buf, offset, byteLength) { + validateNumber(offset, 'offset'); + if (buf[offset] === undefined || buf[offset + byteLength] === undefined) { + boundsError(offset, buf.length - (byteLength + 1)); + } +} +function checkIntBI(value, min, max, buf, offset, byteLength) { + if (value > max || value < min) { + const n = typeof min === 'bigint' ? 'n' : ''; + let range; + if (byteLength > 3) { + if (min === 0 || min === BigInt(0)) { + range = `>= 0${n} and < 2${n} ** ${(byteLength + 1) * 8}${n}`; + } else { + range = `>= -(2${n} ** ${(byteLength + 1) * 8 - 1}${n}) and < 2 ** ` + `${(byteLength + 1) * 8 - 1}${n}`; + } + } else { + range = `>= ${min}${n} and <= ${max}${n}`; + } + throw new errors.ERR_OUT_OF_RANGE('value', range, value); + } + checkBounds(buf, offset, byteLength); +} +function validateNumber(value, name) { + if (typeof value !== 'number') { + throw new errors.ERR_INVALID_ARG_TYPE(name, 'number', value); + } +} +function boundsError(value, length, type) { + if (Math.floor(value) !== value) { + validateNumber(value, type); + throw new errors.ERR_OUT_OF_RANGE(type || 'offset', 'an integer', value); + } + if (length < 0) { + throw new errors.ERR_BUFFER_OUT_OF_BOUNDS(); + } + throw new errors.ERR_OUT_OF_RANGE(type || 'offset', `>= ${type ? 1 : 0} and <= ${length}`, value); +} + +// HELPER FUNCTIONS +// ================ + +const INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g; +function base64clean(str) { + // Node takes equal signs as end of the Base64 encoding + str = str.split('=')[0]; + // Node strips out invalid characters like \n and \t from the string, base64-js does not + str = str.trim().replace(INVALID_BASE64_RE, ''); + // Node converts strings with length < 2 to '' + if (str.length < 2) return ''; + // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not + while (str.length % 4 !== 0) { + str = str + '='; + } + return str; +} +function utf8ToBytes(string, units) { + units = units || Infinity; + let codePoint; + const length = string.length; + let leadSurrogate = null; + const bytes = []; + for (let i = 0; i < length; ++i) { + codePoint = string.charCodeAt(i); + + // is surrogate component + if (codePoint > 0xD7FF && codePoint < 0xE000) { + // last char was a lead + if (!leadSurrogate) { + // no lead yet + if (codePoint > 0xDBFF) { + // unexpected trail + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD); + continue; + } else if (i + 1 === length) { + // unpaired lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD); + continue; + } + + // valid lead + leadSurrogate = codePoint; + continue; + } + + // 2 leads in a row + if (codePoint < 0xDC00) { + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD); + leadSurrogate = codePoint; + continue; + } + + // valid surrogate pair + codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000; + } else if (leadSurrogate) { + // valid bmp char, but last char was a lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD); + } + leadSurrogate = null; + + // encode utf8 + if (codePoint < 0x80) { + if ((units -= 1) < 0) break; + bytes.push(codePoint); + } else if (codePoint < 0x800) { + if ((units -= 2) < 0) break; + bytes.push(codePoint >> 0x6 | 0xC0, codePoint & 0x3F | 0x80); + } else if (codePoint < 0x10000) { + if ((units -= 3) < 0) break; + bytes.push(codePoint >> 0xC | 0xE0, codePoint >> 0x6 & 0x3F | 0x80, codePoint & 0x3F | 0x80); + } else if (codePoint < 0x110000) { + if ((units -= 4) < 0) break; + bytes.push(codePoint >> 0x12 | 0xF0, codePoint >> 0xC & 0x3F | 0x80, codePoint >> 0x6 & 0x3F | 0x80, codePoint & 0x3F | 0x80); + } else { + throw new Error('Invalid code point'); + } + } + return bytes; +} +function asciiToBytes(str) { + const byteArray = []; + for (let i = 0; i < str.length; ++i) { + // Node's code seems to be doing this and not & 0x7F.. + byteArray.push(str.charCodeAt(i) & 0xFF); + } + return byteArray; +} +function utf16leToBytes(str, units) { + let c, hi, lo; + const byteArray = []; + for (let i = 0; i < str.length; ++i) { + if ((units -= 2) < 0) break; + c = str.charCodeAt(i); + hi = c >> 8; + lo = c % 256; + byteArray.push(lo); + byteArray.push(hi); + } + return byteArray; +} +function base64ToBytes(str) { + return base64.toByteArray(base64clean(str)); +} +function blitBuffer(src, dst, offset, length) { + let i; + for (i = 0; i < length; ++i) { + if (i + offset >= dst.length || i >= src.length) break; + dst[i + offset] = src[i]; + } + return i; +} + +// ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass +// the `instanceof` check but they should be treated as of that type. +// See: https://github.com/feross/buffer/issues/166 +function isInstance(obj, type) { + return obj instanceof type || obj != null && obj.constructor != null && obj.constructor.name != null && obj.constructor.name === type.name; +} +function numberIsNaN(obj) { + // For IE11 support + return obj !== obj; // eslint-disable-line no-self-compare +} + +// Create lookup table for `toString('hex')` +// See: https://github.com/feross/buffer/issues/219 +const hexSliceLookupTable = function () { + const alphabet = '0123456789abcdef'; + const table = new Array(256); + for (let i = 0; i < 16; ++i) { + const i16 = i * 16; + for (let j = 0; j < 16; ++j) { + table[i16 + j] = alphabet[i] + alphabet[j]; + } + } + return table; +}(); + +// Return not function with Error if BigInt not supported +function defineBigIntMethod(fn) { + return typeof BigInt === 'undefined' ? BufferBigIntNotDefined : fn; +} +function BufferBigIntNotDefined() { + throw new Error('BigInt not supported'); +} + +/***/ }), + +/***/ "./node_modules/css-loader/dist/runtime/api.js": +/*!*****************************************************!*\ + !*** ./node_modules/css-loader/dist/runtime/api.js ***! + \*****************************************************/ +/***/ ((module) => { + +"use strict"; + + +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +module.exports = function (cssWithMappingToString) { + var list = []; + + // return the list of modules as css string + list.toString = function toString() { + return this.map(function (item) { + var content = ""; + var needLayer = typeof item[5] !== "undefined"; + if (item[4]) { + content += "@supports (".concat(item[4], ") {"); + } + if (item[2]) { + content += "@media ".concat(item[2], " {"); + } + if (needLayer) { + content += "@layer".concat(item[5].length > 0 ? " ".concat(item[5]) : "", " {"); + } + content += cssWithMappingToString(item); + if (needLayer) { + content += "}"; + } + if (item[2]) { + content += "}"; + } + if (item[4]) { + content += "}"; + } + return content; + }).join(""); + }; + + // import a list of modules into the list + list.i = function i(modules, media, dedupe, supports, layer) { + if (typeof modules === "string") { + modules = [[null, modules, undefined]]; + } + var alreadyImportedModules = {}; + if (dedupe) { + for (var k = 0; k < this.length; k++) { + var id = this[k][0]; + if (id != null) { + alreadyImportedModules[id] = true; + } + } + } + for (var _k = 0; _k < modules.length; _k++) { + var item = [].concat(modules[_k]); + if (dedupe && alreadyImportedModules[item[0]]) { + continue; + } + if (typeof layer !== "undefined") { + if (typeof item[5] === "undefined") { + item[5] = layer; + } else { + item[1] = "@layer".concat(item[5].length > 0 ? " ".concat(item[5]) : "", " {").concat(item[1], "}"); + item[5] = layer; + } + } + if (media) { + if (!item[2]) { + item[2] = media; + } else { + item[1] = "@media ".concat(item[2], " {").concat(item[1], "}"); + item[2] = media; + } + } + if (supports) { + if (!item[4]) { + item[4] = "".concat(supports); + } else { + item[1] = "@supports (".concat(item[4], ") {").concat(item[1], "}"); + item[4] = supports; + } + } + list.push(item); + } + }; + return list; +}; + +/***/ }), + +/***/ "./node_modules/css-loader/dist/runtime/getUrl.js": +/*!********************************************************!*\ + !*** ./node_modules/css-loader/dist/runtime/getUrl.js ***! + \********************************************************/ +/***/ ((module) => { + +"use strict"; + + +module.exports = function (url, options) { + if (!options) { + options = {}; + } + if (!url) { + return url; + } + url = String(url.__esModule ? url.default : url); + + // If url is already wrapped in quotes, remove them + if (/^['"].*['"]$/.test(url)) { + url = url.slice(1, -1); + } + if (options.hash) { + url += options.hash; + } + + // Should url be wrapped? + // See https://drafts.csswg.org/css-values-3/#urls + if (/["'() \t\n]|(%20)/.test(url) || options.needQuotes) { + return "\"".concat(url.replace(/"/g, '\\"').replace(/\n/g, "\\n"), "\""); + } + return url; +}; + +/***/ }), + +/***/ "./node_modules/css-loader/dist/runtime/sourceMaps.js": +/*!************************************************************!*\ + !*** ./node_modules/css-loader/dist/runtime/sourceMaps.js ***! + \************************************************************/ +/***/ ((module) => { + +"use strict"; + + +module.exports = function (item) { + var content = item[1]; + var cssMapping = item[3]; + if (!cssMapping) { + return content; + } + if (typeof btoa === "function") { + var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(cssMapping)))); + var data = "sourceMappingURL=data:application/json;charset=utf-8;base64,".concat(base64); + var sourceMapping = "/*# ".concat(data, " */"); + return [content].concat([sourceMapping]).join("\n"); + } + return [content].join("\n"); +}; + +/***/ }), + +/***/ "./node_modules/custom-event-polyfill/polyfill.js": +/*!********************************************************!*\ + !*** ./node_modules/custom-event-polyfill/polyfill.js ***! + \********************************************************/ +/***/ (() => { + +// Polyfill for creating CustomEvents on IE9/10/11 + +// code pulled from: +// https://github.com/d4tocchini/customevent-polyfill +// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent#Polyfill + +(function () { + if (typeof window === 'undefined') { + return; + } + try { + var ce = new window.CustomEvent('test', { + cancelable: true + }); + ce.preventDefault(); + if (ce.defaultPrevented !== true) { + // IE has problems with .preventDefault() on custom events + // http://stackoverflow.com/questions/23349191 + throw new Error('Could not prevent default'); + } + } catch (e) { + var CustomEvent = function (event, params) { + var evt, origPrevent; + params = params || {}; + params.bubbles = !!params.bubbles; + params.cancelable = !!params.cancelable; + evt = document.createEvent('CustomEvent'); + evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); + origPrevent = evt.preventDefault; + evt.preventDefault = function () { + origPrevent.call(this); + try { + Object.defineProperty(this, 'defaultPrevented', { + get: function () { + return true; + } + }); + } catch (e) { + this.defaultPrevented = true; + } + }; + return evt; + }; + CustomEvent.prototype = window.Event.prototype; + window.CustomEvent = CustomEvent; // expose definition to window + } +})(); + +/***/ }), + +/***/ "./node_modules/debug/browser.js": +/*!***************************************!*\ + !*** ./node_modules/debug/browser.js ***! + \***************************************/ +/***/ ((module, exports, __webpack_require__) => { + +/** + * This is the web browser implementation of `debug()`. + * + * Expose `debug()` as the module. + */ + +exports = module.exports = __webpack_require__(/*! ./debug */ "./node_modules/debug/debug.js"); +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; +exports.storage = 'undefined' != typeof chrome && 'undefined' != typeof chrome.storage ? chrome.storage.local : localstorage(); + +/** + * Colors. + */ + +exports.colors = ['lightseagreen', 'forestgreen', 'goldenrod', 'dodgerblue', 'darkorchid', 'crimson']; + +/** + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ + +function useColors() { + // is webkit? http://stackoverflow.com/a/16459606/376773 + return 'WebkitAppearance' in document.documentElement.style || + // is firebug? http://stackoverflow.com/a/398120/376773 + window.console && (console.firebug || console.exception && console.table) || + // is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31; +} + +/** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ + +exports.formatters.j = function (v) { + return JSON.stringify(v); +}; + +/** + * Colorize log arguments if enabled. + * + * @api public + */ + +function formatArgs() { + var args = arguments; + var useColors = this.useColors; + args[0] = (useColors ? '%c' : '') + this.namespace + (useColors ? ' %c' : ' ') + args[0] + (useColors ? '%c ' : ' '); + if (!useColors) return args; + var c = 'color: ' + this.color; + args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1)); + + // the final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + var index = 0; + var lastC = 0; + args[0].replace(/%[a-z%]/g, function (match) { + if ('%%' === match) return; + index++; + if ('%c' === match) { + // we only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); + args.splice(lastC, 0, c); + return args; +} + +/** + * Invokes `console.log()` when available. + * No-op when `console.log` is not a "function". + * + * @api public + */ + +function log() { + // this hackery is required for IE8/9, where + // the `console.log` function doesn't have 'apply' + return 'object' === typeof console && console.log && Function.prototype.apply.call(console.log, console, arguments); +} + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ + +function save(namespaces) { + try { + if (null == namespaces) { + exports.storage.removeItem('debug'); + } else { + exports.storage.debug = namespaces; + } + } catch (e) {} +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + +function load() { + var r; + try { + r = exports.storage.debug; + } catch (e) {} + return r; +} + +/** + * Enable namespaces listed in `localStorage.debug` initially. + */ + +exports.enable(load()); + +/** + * Localstorage attempts to return the localstorage. + * + * This is necessary because safari throws + * when a user disables cookies/localstorage + * and you attempt to access it. + * + * @return {LocalStorage} + * @api private + */ + +function localstorage() { + try { + return window.localStorage; + } catch (e) {} +} + +/***/ }), + +/***/ "./node_modules/debug/debug.js": +/*!*************************************!*\ + !*** ./node_modules/debug/debug.js ***! + \*************************************/ +/***/ ((module, exports) => { + +/** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + * + * Expose `debug()` as the module. + */ + +exports = module.exports = debug; +exports.coerce = coerce; +exports.disable = disable; +exports.enable = enable; +exports.enabled = enabled; + +/** + * The currently active debug mode names, and names to skip. + */ + +exports.names = []; +exports.skips = []; + +/** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lowercased letter, i.e. "n". + */ + +exports.formatters = {}; + +/** + * Previously assigned color. + */ + +var prevColor = 0; + +/** + * Select a color. + * + * @return {Number} + * @api private + */ + +function selectColor() { + return exports.colors[prevColor++ % exports.colors.length]; +} + +/** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ + +function debug(namespace) { + // define the `disabled` version + function disabled() {} + disabled.enabled = false; + + // define the `enabled` version + function enabled() { + var self = enabled; + + // add the `color` if not set + if (null == self.useColors) self.useColors = exports.useColors(); + if (null == self.color && self.useColors) self.color = selectColor(); + var args = Array.prototype.slice.call(arguments); + args[0] = exports.coerce(args[0]); + if ('string' !== typeof args[0]) { + // anything else let's inspect with %o + args = ['%o'].concat(args); + } + + // apply any `formatters` transformations + var index = 0; + args[0] = args[0].replace(/%([a-z%])/g, function (match, format) { + // if we encounter an escaped % then don't increase the array index + if (match === '%%') return match; + index++; + var formatter = exports.formatters[format]; + if ('function' === typeof formatter) { + var val = args[index]; + match = formatter.call(self, val); + + // now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; + } + return match; + }); + if ('function' === typeof exports.formatArgs) { + args = exports.formatArgs.apply(self, args); + } + var logFn = enabled.log || exports.log || console.log.bind(console); + logFn.apply(self, args); + } + enabled.enabled = true; + var fn = exports.enabled(namespace) ? enabled : disabled; + fn.namespace = namespace; + return fn; +} + +/** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ + +function enable(namespaces) { + exports.save(namespaces); + var split = (namespaces || '').split(/[\s,]+/); + var len = split.length; + for (var i = 0; i < len; i++) { + if (!split[i]) continue; // ignore empty strings + namespaces = split[i].replace(/\*/g, '.*?'); + if (namespaces[0] === '-') { + exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); + } else { + exports.names.push(new RegExp('^' + namespaces + '$')); + } + } +} + +/** + * Disable debug output. + * + * @api public + */ + +function disable() { + exports.enable(''); +} + +/** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + +function enabled(name) { + var i, len; + for (i = 0, len = exports.skips.length; i < len; i++) { + if (exports.skips[i].test(name)) { + return false; + } + } + for (i = 0, len = exports.names.length; i < len; i++) { + if (exports.names[i].test(name)) { + return true; + } + } + return false; +} + +/** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + +function coerce(val) { + if (val instanceof Error) return val.stack || val.message; + return val; +} + +/***/ }), + +/***/ "./node_modules/deep-assign/index.js": +/*!*******************************************!*\ + !*** ./node_modules/deep-assign/index.js ***! + \*******************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +"use strict"; + + +var isObj = __webpack_require__(/*! is-obj */ "./node_modules/is-obj/index.js"); +var hasOwnProperty = Object.prototype.hasOwnProperty; +var propIsEnumerable = Object.prototype.propertyIsEnumerable; +function toObject(val) { + if (val === null || val === undefined) { + throw new TypeError('Sources cannot be null or undefined'); + } + return Object(val); +} +function assignKey(to, from, key) { + var val = from[key]; + if (val === undefined || val === null) { + return; + } + if (hasOwnProperty.call(to, key)) { + if (to[key] === undefined || to[key] === null) { + throw new TypeError('Cannot convert undefined or null to object (' + key + ')'); + } + } + if (!hasOwnProperty.call(to, key) || !isObj(val)) { + to[key] = val; + } else { + to[key] = assign(Object(to[key]), from[key]); + } +} +function assign(to, from) { + if (to === from) { + return to; + } + from = Object(from); + for (var key in from) { + if (hasOwnProperty.call(from, key)) { + assignKey(to, from, key); + } + } + if (Object.getOwnPropertySymbols) { + var symbols = Object.getOwnPropertySymbols(from); + for (var i = 0; i < symbols.length; i++) { + if (propIsEnumerable.call(from, symbols[i])) { + assignKey(to, from, symbols[i]); + } + } + } + return to; +} +module.exports = function deepAssign(target) { + target = toObject(target); + for (var s = 1; s < arguments.length; s++) { + assign(target, arguments[s]); + } + return target; +}; + +/***/ }), + +/***/ "./node_modules/dtype/index.js": +/*!*************************************!*\ + !*** ./node_modules/dtype/index.js ***! + \*************************************/ +/***/ ((module) => { + +module.exports = function (dtype) { + switch (dtype) { + case 'int8': + return Int8Array; + case 'int16': + return Int16Array; + case 'int32': + return Int32Array; + case 'uint8': + return Uint8Array; + case 'uint16': + return Uint16Array; + case 'uint32': + return Uint32Array; + case 'float32': + return Float32Array; + case 'float64': + return Float64Array; + case 'array': + return Array; + case 'uint8_clamped': + return Uint8ClampedArray; + } +}; + +/***/ }), + +/***/ "./node_modules/flatten-vertex-data/index.js": +/*!***************************************************!*\ + !*** ./node_modules/flatten-vertex-data/index.js ***! + \***************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/*eslint new-cap:0*/ +var dtype = __webpack_require__(/*! dtype */ "./node_modules/dtype/index.js"); +module.exports = flattenVertexData; +function flattenVertexData(data, output, offset) { + if (!data) throw new TypeError('must specify data as first parameter'); + offset = +(offset || 0) | 0; + if (Array.isArray(data) && data[0] && typeof data[0][0] === 'number') { + var dim = data[0].length; + var length = data.length * dim; + var i, j, k, l; + + // no output specified, create a new typed array + if (!output || typeof output === 'string') { + output = new (dtype(output || 'float32'))(length + offset); + } + var dstLength = output.length - offset; + if (length !== dstLength) { + throw new Error('source length ' + length + ' (' + dim + 'x' + data.length + ')' + ' does not match destination length ' + dstLength); + } + for (i = 0, k = offset; i < data.length; i++) { + for (j = 0; j < dim; j++) { + output[k++] = data[i][j] === null ? NaN : data[i][j]; + } + } + } else { + if (!output || typeof output === 'string') { + // no output, create a new one + var Ctor = dtype(output || 'float32'); + + // handle arrays separately due to possible nulls + if (Array.isArray(data) || output === 'array') { + output = new Ctor(data.length + offset); + for (i = 0, k = offset, l = output.length; k < l; k++, i++) { + output[k] = data[i] === null ? NaN : data[i]; + } + } else { + if (offset === 0) { + output = new Ctor(data); + } else { + output = new Ctor(data.length + offset); + output.set(data, offset); + } + } + } else { + // store output in existing array + output.set(data, offset); + } + } + return output; +} + +/***/ }), + +/***/ "./node_modules/global/window.js": +/*!***************************************!*\ + !*** ./node_modules/global/window.js ***! + \***************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var win; +if (typeof window !== "undefined") { + win = window; +} else if (typeof __webpack_require__.g !== "undefined") { + win = __webpack_require__.g; +} else if (typeof self !== "undefined") { + win = self; +} else { + win = {}; +} +module.exports = win; + +/***/ }), + +/***/ "./node_modules/ieee754/index.js": +/*!***************************************!*\ + !*** ./node_modules/ieee754/index.js ***! + \***************************************/ +/***/ ((__unused_webpack_module, exports) => { + +/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh */ +exports.read = function (buffer, offset, isLE, mLen, nBytes) { + var e, m; + var eLen = nBytes * 8 - mLen - 1; + var eMax = (1 << eLen) - 1; + var eBias = eMax >> 1; + var nBits = -7; + var i = isLE ? nBytes - 1 : 0; + var d = isLE ? -1 : 1; + var s = buffer[offset + i]; + i += d; + e = s & (1 << -nBits) - 1; + s >>= -nBits; + nBits += eLen; + for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {} + m = e & (1 << -nBits) - 1; + e >>= -nBits; + nBits += mLen; + for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {} + if (e === 0) { + e = 1 - eBias; + } else if (e === eMax) { + return m ? NaN : (s ? -1 : 1) * Infinity; + } else { + m = m + Math.pow(2, mLen); + e = e - eBias; + } + return (s ? -1 : 1) * m * Math.pow(2, e - mLen); +}; +exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { + var e, m, c; + var eLen = nBytes * 8 - mLen - 1; + var eMax = (1 << eLen) - 1; + var eBias = eMax >> 1; + var rt = mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0; + var i = isLE ? 0 : nBytes - 1; + var d = isLE ? 1 : -1; + var s = value < 0 || value === 0 && 1 / value < 0 ? 1 : 0; + value = Math.abs(value); + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0; + e = eMax; + } else { + e = Math.floor(Math.log(value) / Math.LN2); + if (value * (c = Math.pow(2, -e)) < 1) { + e--; + c *= 2; + } + if (e + eBias >= 1) { + value += rt / c; + } else { + value += rt * Math.pow(2, 1 - eBias); + } + if (value * c >= 2) { + e++; + c /= 2; + } + if (e + eBias >= eMax) { + m = 0; + e = eMax; + } else if (e + eBias >= 1) { + m = (value * c - 1) * Math.pow(2, mLen); + e = e + eBias; + } else { + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); + e = 0; + } + } + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} + e = e << mLen | m; + eLen += mLen; + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} + buffer[offset + i - d] |= s * 128; +}; + +/***/ }), + +/***/ "./node_modules/inherits/inherits_browser.js": +/*!***************************************************!*\ + !*** ./node_modules/inherits/inherits_browser.js ***! + \***************************************************/ +/***/ ((module) => { + +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + if (superCtor) { + ctor.super_ = superCtor; + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + } + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + if (superCtor) { + ctor.super_ = superCtor; + var TempCtor = function () {}; + TempCtor.prototype = superCtor.prototype; + ctor.prototype = new TempCtor(); + ctor.prototype.constructor = ctor; + } + }; +} + +/***/ }), + +/***/ "./node_modules/is-buffer/index.js": +/*!*****************************************!*\ + !*** ./node_modules/is-buffer/index.js ***! + \*****************************************/ +/***/ ((module) => { + +/*! + * Determine if an object is a Buffer + * + * @author Feross Aboukhadijeh + * @license MIT + */ + +// The _isBuffer check is for Safari 5-7 support, because it's missing +// Object.prototype.constructor. Remove this eventually +module.exports = function (obj) { + return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer); +}; +function isBuffer(obj) { + return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj); +} + +// For Node v0.10 support. Remove this eventually. +function isSlowBuffer(obj) { + return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0)); +} + +/***/ }), + +/***/ "./node_modules/is-function/index.js": +/*!*******************************************!*\ + !*** ./node_modules/is-function/index.js ***! + \*******************************************/ +/***/ ((module) => { + +module.exports = isFunction; +var toString = Object.prototype.toString; +function isFunction(fn) { + if (!fn) { + return false; + } + var string = toString.call(fn); + return string === '[object Function]' || typeof fn === 'function' && string !== '[object RegExp]' || typeof window !== 'undefined' && ( + // IE8 and below + fn === window.setTimeout || fn === window.alert || fn === window.confirm || fn === window.prompt); +} +; + +/***/ }), + +/***/ "./node_modules/is-obj/index.js": +/*!**************************************!*\ + !*** ./node_modules/is-obj/index.js ***! + \**************************************/ +/***/ ((module) => { + +"use strict"; + + +module.exports = function (x) { + var type = typeof x; + return x !== null && (type === 'object' || type === 'function'); +}; + +/***/ }), + +/***/ "./node_modules/layout-bmfont-text/index.js": +/*!**************************************************!*\ + !*** ./node_modules/layout-bmfont-text/index.js ***! + \**************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var wordWrap = __webpack_require__(/*! word-wrapper */ "./node_modules/word-wrapper/index.js"); +var xtend = __webpack_require__(/*! xtend */ "./node_modules/xtend/immutable.js"); +var number = __webpack_require__(/*! as-number */ "./node_modules/as-number/index.js"); +var X_HEIGHTS = ['x', 'e', 'a', 'o', 'n', 's', 'r', 'c', 'u', 'm', 'v', 'w', 'z']; +var M_WIDTHS = ['m', 'w']; +var CAP_HEIGHTS = ['H', 'I', 'N', 'E', 'F', 'K', 'L', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']; +var TAB_ID = '\t'.charCodeAt(0); +var SPACE_ID = ' '.charCodeAt(0); +var ALIGN_LEFT = 0, + ALIGN_CENTER = 1, + ALIGN_RIGHT = 2; +module.exports = function createLayout(opt) { + return new TextLayout(opt); +}; +function TextLayout(opt) { + this.glyphs = []; + this._measure = this.computeMetrics.bind(this); + this.update(opt); +} +TextLayout.prototype.update = function (opt) { + opt = xtend({ + measure: this._measure + }, opt); + this._opt = opt; + this._opt.tabSize = number(this._opt.tabSize, 4); + if (!opt.font) throw new Error('must provide a valid bitmap font'); + var glyphs = this.glyphs; + var text = opt.text || ''; + var font = opt.font; + this._setupSpaceGlyphs(font); + var lines = wordWrap.lines(text, opt); + var minWidth = opt.width || 0; + + //clear glyphs + glyphs.length = 0; + + //get max line width + var maxLineWidth = lines.reduce(function (prev, line) { + return Math.max(prev, line.width, minWidth); + }, 0); + + //the pen position + var x = 0; + var y = 0; + var lineHeight = number(opt.lineHeight, font.common.lineHeight); + var baseline = font.common.base; + var descender = lineHeight - baseline; + var letterSpacing = opt.letterSpacing || 0; + var height = lineHeight * lines.length - descender; + var align = getAlignType(this._opt.align); + + //draw text along baseline + y -= height; + + //the metrics for this text layout + this._width = maxLineWidth; + this._height = height; + this._descender = lineHeight - baseline; + this._baseline = baseline; + this._xHeight = getXHeight(font); + this._capHeight = getCapHeight(font); + this._lineHeight = lineHeight; + this._ascender = lineHeight - descender - this._xHeight; + + //layout each glyph + var self = this; + lines.forEach(function (line, lineIndex) { + var start = line.start; + var end = line.end; + var lineWidth = line.width; + var lastGlyph; + + //for each glyph in that line... + for (var i = start; i < end; i++) { + var id = text.charCodeAt(i); + var glyph = self.getGlyph(font, id); + if (glyph) { + if (lastGlyph) x += getKerning(font, lastGlyph.id, glyph.id); + var tx = x; + if (align === ALIGN_CENTER) tx += (maxLineWidth - lineWidth) / 2;else if (align === ALIGN_RIGHT) tx += maxLineWidth - lineWidth; + glyphs.push({ + position: [tx, y], + data: glyph, + index: i, + line: lineIndex + }); + + //move pen forward + x += glyph.xadvance + letterSpacing; + lastGlyph = glyph; + } + } + + //next line down + y += lineHeight; + x = 0; + }); + this._linesTotal = lines.length; +}; +TextLayout.prototype._setupSpaceGlyphs = function (font) { + //These are fallbacks, when the font doesn't include + //' ' or '\t' glyphs + this._fallbackSpaceGlyph = null; + this._fallbackTabGlyph = null; + if (!font.chars || font.chars.length === 0) return; + + //try to get space glyph + //then fall back to the 'm' or 'w' glyphs + //then fall back to the first glyph available + var space = getGlyphById(font, SPACE_ID) || getMGlyph(font) || font.chars[0]; + + //and create a fallback for tab + var tabWidth = this._opt.tabSize * space.xadvance; + this._fallbackSpaceGlyph = space; + this._fallbackTabGlyph = xtend(space, { + x: 0, + y: 0, + xadvance: tabWidth, + id: TAB_ID, + xoffset: 0, + yoffset: 0, + width: 0, + height: 0 + }); +}; +TextLayout.prototype.getGlyph = function (font, id) { + var glyph = getGlyphById(font, id); + if (glyph) return glyph;else if (id === TAB_ID) return this._fallbackTabGlyph;else if (id === SPACE_ID) return this._fallbackSpaceGlyph; + return null; +}; +TextLayout.prototype.computeMetrics = function (text, start, end, width) { + var letterSpacing = this._opt.letterSpacing || 0; + var font = this._opt.font; + var curPen = 0; + var curWidth = 0; + var count = 0; + var glyph; + var lastGlyph; + if (!font.chars || font.chars.length === 0) { + return { + start: start, + end: start, + width: 0 + }; + } + end = Math.min(text.length, end); + for (var i = start; i < end; i++) { + var id = text.charCodeAt(i); + var glyph = this.getGlyph(font, id); + if (glyph) { + //move pen forward + var xoff = glyph.xoffset; + var kern = lastGlyph ? getKerning(font, lastGlyph.id, glyph.id) : 0; + curPen += kern; + var nextPen = curPen + glyph.xadvance + letterSpacing; + var nextWidth = curPen + glyph.width; + + //we've hit our limit; we can't move onto the next glyph + if (nextWidth >= width || nextPen >= width) break; + + //otherwise continue along our line + curPen = nextPen; + curWidth = nextWidth; + lastGlyph = glyph; + } + count++; + } + + //make sure rightmost edge lines up with rendered glyphs + if (lastGlyph) curWidth += lastGlyph.xoffset; + return { + start: start, + end: start + count, + width: curWidth + }; +} + +//getters for the private vars +; +['width', 'height', 'descender', 'ascender', 'xHeight', 'baseline', 'capHeight', 'lineHeight'].forEach(addGetter); +function addGetter(name) { + Object.defineProperty(TextLayout.prototype, name, { + get: wrapper(name), + configurable: true + }); +} + +//create lookups for private vars +function wrapper(name) { + return new Function(['return function ' + name + '() {', ' return this._' + name, '}'].join('\n'))(); +} +function getGlyphById(font, id) { + if (!font.chars || font.chars.length === 0) return null; + var glyphIdx = findChar(font.chars, id); + if (glyphIdx >= 0) return font.chars[glyphIdx]; + return null; +} +function getXHeight(font) { + for (var i = 0; i < X_HEIGHTS.length; i++) { + var id = X_HEIGHTS[i].charCodeAt(0); + var idx = findChar(font.chars, id); + if (idx >= 0) return font.chars[idx].height; + } + return 0; +} +function getMGlyph(font) { + for (var i = 0; i < M_WIDTHS.length; i++) { + var id = M_WIDTHS[i].charCodeAt(0); + var idx = findChar(font.chars, id); + if (idx >= 0) return font.chars[idx]; + } + return 0; +} +function getCapHeight(font) { + for (var i = 0; i < CAP_HEIGHTS.length; i++) { + var id = CAP_HEIGHTS[i].charCodeAt(0); + var idx = findChar(font.chars, id); + if (idx >= 0) return font.chars[idx].height; + } + return 0; +} +function getKerning(font, left, right) { + if (!font.kernings || font.kernings.length === 0) return 0; + var table = font.kernings; + for (var i = 0; i < table.length; i++) { + var kern = table[i]; + if (kern.first === left && kern.second === right) return kern.amount; + } + return 0; +} +function getAlignType(align) { + if (align === 'center') return ALIGN_CENTER;else if (align === 'right') return ALIGN_RIGHT; + return ALIGN_LEFT; +} +function findChar(array, value, start) { + start = start || 0; + for (var i = start; i < array.length; i++) { + if (array[i].id === value) { + return i; + } + } + return -1; +} + +/***/ }), + +/***/ "./node_modules/load-bmfont/browser.js": +/*!*********************************************!*\ + !*** ./node_modules/load-bmfont/browser.js ***! + \*********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/* provided dependency */ var Buffer = __webpack_require__(/*! buffer */ "./node_modules/buffer/index.js")["Buffer"]; +var xhr = __webpack_require__(/*! xhr */ "./node_modules/xhr/index.js"); +var noop = function () {}; +var parseASCII = __webpack_require__(/*! parse-bmfont-ascii */ "./node_modules/parse-bmfont-ascii/index.js"); +var parseXML = __webpack_require__(/*! parse-bmfont-xml */ "./node_modules/parse-bmfont-xml/lib/browser.js"); +var readBinary = __webpack_require__(/*! parse-bmfont-binary */ "./node_modules/parse-bmfont-binary/index.js"); +var isBinaryFormat = __webpack_require__(/*! ./lib/is-binary */ "./node_modules/load-bmfont/lib/is-binary.js"); +var xtend = __webpack_require__(/*! xtend */ "./node_modules/xtend/immutable.js"); +var xml2 = function hasXML2() { + return self.XMLHttpRequest && "withCredentials" in new XMLHttpRequest(); +}(); +module.exports = function (opt, cb) { + cb = typeof cb === 'function' ? cb : noop; + if (typeof opt === 'string') opt = { + uri: opt + };else if (!opt) opt = {}; + var expectBinary = opt.binary; + if (expectBinary) opt = getBinaryOpts(opt); + xhr(opt, function (err, res, body) { + if (err) return cb(err); + if (!/^2/.test(res.statusCode)) return cb(new Error('http status code: ' + res.statusCode)); + if (!body) return cb(new Error('no body result')); + var binary = false; + + //if the response type is an array buffer, + //we need to convert it into a regular Buffer object + if (isArrayBuffer(body)) { + var array = new Uint8Array(body); + body = Buffer.from(array, 'binary'); + } + + //now check the string/Buffer response + //and see if it has a binary BMF header + if (isBinaryFormat(body)) { + binary = true; + //if we have a string, turn it into a Buffer + if (typeof body === 'string') body = Buffer.from(body, 'binary'); + } + + //we are not parsing a binary format, just ASCII/XML/etc + if (!binary) { + //might still be a buffer if responseType is 'arraybuffer' + if (Buffer.isBuffer(body)) body = body.toString(opt.encoding); + body = body.trim(); + } + var result; + try { + var type = res.headers['content-type']; + if (binary) result = readBinary(body);else if (/json/.test(type) || body.charAt(0) === '{') result = JSON.parse(body);else if (/xml/.test(type) || body.charAt(0) === '<') result = parseXML(body);else result = parseASCII(body); + } catch (e) { + cb(new Error('error parsing font ' + e.message)); + cb = noop; + } + cb(null, result); + }); +}; +function isArrayBuffer(arr) { + var str = Object.prototype.toString; + return str.call(arr) === '[object ArrayBuffer]'; +} +function getBinaryOpts(opt) { + //IE10+ and other modern browsers support array buffers + if (xml2) return xtend(opt, { + responseType: 'arraybuffer' + }); + if (typeof self.XMLHttpRequest === 'undefined') throw new Error('your browser does not support XHR loading'); + + //IE9 and XML1 browsers could still use an override + var req = new self.XMLHttpRequest(); + req.overrideMimeType('text/plain; charset=x-user-defined'); + return xtend({ + xhr: req + }, opt); +} + +/***/ }), + +/***/ "./node_modules/load-bmfont/lib/is-binary.js": +/*!***************************************************!*\ + !*** ./node_modules/load-bmfont/lib/is-binary.js ***! + \***************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/* provided dependency */ var Buffer = __webpack_require__(/*! buffer */ "./node_modules/buffer/index.js")["Buffer"]; +var equal = __webpack_require__(/*! buffer-equal */ "./node_modules/buffer-equal/index.js"); +var HEADER = Buffer.from([66, 77, 70, 3]); +module.exports = function (buf) { + if (typeof buf === 'string') return buf.substring(0, 3) === 'BMF'; + return buf.length > 4 && equal(buf.slice(0, 4), HEADER); +}; + +/***/ }), + +/***/ "./node_modules/object-assign/index.js": +/*!*********************************************!*\ + !*** ./node_modules/object-assign/index.js ***! + \*********************************************/ +/***/ ((module) => { + +"use strict"; +/* +object-assign +(c) Sindre Sorhus +@license MIT +*/ + + + +/* eslint-disable no-unused-vars */ +var getOwnPropertySymbols = Object.getOwnPropertySymbols; +var hasOwnProperty = Object.prototype.hasOwnProperty; +var propIsEnumerable = Object.prototype.propertyIsEnumerable; +function toObject(val) { + if (val === null || val === undefined) { + throw new TypeError('Object.assign cannot be called with null or undefined'); + } + return Object(val); +} +function shouldUseNative() { + try { + if (!Object.assign) { + return false; + } + + // Detect buggy property enumeration order in older V8 versions. + + // https://bugs.chromium.org/p/v8/issues/detail?id=4118 + var test1 = new String('abc'); // eslint-disable-line no-new-wrappers + test1[5] = 'de'; + if (Object.getOwnPropertyNames(test1)[0] === '5') { + return false; + } + + // https://bugs.chromium.org/p/v8/issues/detail?id=3056 + var test2 = {}; + for (var i = 0; i < 10; i++) { + test2['_' + String.fromCharCode(i)] = i; + } + var order2 = Object.getOwnPropertyNames(test2).map(function (n) { + return test2[n]; + }); + if (order2.join('') !== '0123456789') { + return false; + } + + // https://bugs.chromium.org/p/v8/issues/detail?id=3056 + var test3 = {}; + 'abcdefghijklmnopqrst'.split('').forEach(function (letter) { + test3[letter] = letter; + }); + if (Object.keys(Object.assign({}, test3)).join('') !== 'abcdefghijklmnopqrst') { + return false; + } + return true; + } catch (err) { + // We don't expect any of the above to throw, but better to be safe. + return false; + } +} +module.exports = shouldUseNative() ? Object.assign : function (target, source) { + var from; + var to = toObject(target); + var symbols; + for (var s = 1; s < arguments.length; s++) { + from = Object(arguments[s]); + for (var key in from) { + if (hasOwnProperty.call(from, key)) { + to[key] = from[key]; + } + } + if (getOwnPropertySymbols) { + symbols = getOwnPropertySymbols(from); + for (var i = 0; i < symbols.length; i++) { + if (propIsEnumerable.call(from, symbols[i])) { + to[symbols[i]] = from[symbols[i]]; + } + } + } + } + return to; +}; + +/***/ }), + +/***/ "./node_modules/parse-bmfont-ascii/index.js": +/*!**************************************************!*\ + !*** ./node_modules/parse-bmfont-ascii/index.js ***! + \**************************************************/ +/***/ ((module) => { + +module.exports = function parseBMFontAscii(data) { + if (!data) throw new Error('no data provided'); + data = data.toString().trim(); + var output = { + pages: [], + chars: [], + kernings: [] + }; + var lines = data.split(/\r\n?|\n/g); + if (lines.length === 0) throw new Error('no data in BMFont file'); + for (var i = 0; i < lines.length; i++) { + var lineData = splitLine(lines[i], i); + if (!lineData) + //skip empty lines + continue; + if (lineData.key === 'page') { + if (typeof lineData.data.id !== 'number') throw new Error('malformed file at line ' + i + ' -- needs page id=N'); + if (typeof lineData.data.file !== 'string') throw new Error('malformed file at line ' + i + ' -- needs page file="path"'); + output.pages[lineData.data.id] = lineData.data.file; + } else if (lineData.key === 'chars' || lineData.key === 'kernings') { + //... do nothing for these two ... + } else if (lineData.key === 'char') { + output.chars.push(lineData.data); + } else if (lineData.key === 'kerning') { + output.kernings.push(lineData.data); + } else { + output[lineData.key] = lineData.data; + } + } + return output; +}; +function splitLine(line, idx) { + line = line.replace(/\t+/g, ' ').trim(); + if (!line) return null; + var space = line.indexOf(' '); + if (space === -1) throw new Error("no named row at line " + idx); + var key = line.substring(0, space); + line = line.substring(space + 1); + //clear "letter" field as it is non-standard and + //requires additional complexity to parse " / = symbols + line = line.replace(/letter=[\'\"]\S+[\'\"]/gi, ''); + line = line.split("="); + line = line.map(function (str) { + return str.trim().match(/(".*?"|[^"\s]+)+(?=\s*|\s*$)/g); + }); + var data = []; + for (var i = 0; i < line.length; i++) { + var dt = line[i]; + if (i === 0) { + data.push({ + key: dt[0], + data: "" + }); + } else if (i === line.length - 1) { + data[data.length - 1].data = parseData(dt[0]); + } else { + data[data.length - 1].data = parseData(dt[0]); + data.push({ + key: dt[1], + data: "" + }); + } + } + var out = { + key: key, + data: {} + }; + data.forEach(function (v) { + out.data[v.key] = v.data; + }); + return out; +} +function parseData(data) { + if (!data || data.length === 0) return ""; + if (data.indexOf('"') === 0 || data.indexOf("'") === 0) return data.substring(1, data.length - 1); + if (data.indexOf(',') !== -1) return parseIntList(data); + return parseInt(data, 10); +} +function parseIntList(data) { + return data.split(',').map(function (val) { + return parseInt(val, 10); + }); +} + +/***/ }), + +/***/ "./node_modules/parse-bmfont-binary/index.js": +/*!***************************************************!*\ + !*** ./node_modules/parse-bmfont-binary/index.js ***! + \***************************************************/ +/***/ ((module) => { + +var HEADER = [66, 77, 70]; +module.exports = function readBMFontBinary(buf) { + if (buf.length < 6) throw new Error('invalid buffer length for BMFont'); + var header = HEADER.every(function (byte, i) { + return buf.readUInt8(i) === byte; + }); + if (!header) throw new Error('BMFont missing BMF byte header'); + var i = 3; + var vers = buf.readUInt8(i++); + if (vers > 3) throw new Error('Only supports BMFont Binary v3 (BMFont App v1.10)'); + var target = { + kernings: [], + chars: [] + }; + for (var b = 0; b < 5; b++) i += readBlock(target, buf, i); + return target; +}; +function readBlock(target, buf, i) { + if (i > buf.length - 1) return 0; + var blockID = buf.readUInt8(i++); + var blockSize = buf.readInt32LE(i); + i += 4; + switch (blockID) { + case 1: + target.info = readInfo(buf, i); + break; + case 2: + target.common = readCommon(buf, i); + break; + case 3: + target.pages = readPages(buf, i, blockSize); + break; + case 4: + target.chars = readChars(buf, i, blockSize); + break; + case 5: + target.kernings = readKernings(buf, i, blockSize); + break; + } + return 5 + blockSize; +} +function readInfo(buf, i) { + var info = {}; + info.size = buf.readInt16LE(i); + var bitField = buf.readUInt8(i + 2); + info.smooth = bitField >> 7 & 1; + info.unicode = bitField >> 6 & 1; + info.italic = bitField >> 5 & 1; + info.bold = bitField >> 4 & 1; + + //fixedHeight is only mentioned in binary spec + if (bitField >> 3 & 1) info.fixedHeight = 1; + info.charset = buf.readUInt8(i + 3) || ''; + info.stretchH = buf.readUInt16LE(i + 4); + info.aa = buf.readUInt8(i + 6); + info.padding = [buf.readInt8(i + 7), buf.readInt8(i + 8), buf.readInt8(i + 9), buf.readInt8(i + 10)]; + info.spacing = [buf.readInt8(i + 11), buf.readInt8(i + 12)]; + info.outline = buf.readUInt8(i + 13); + info.face = readStringNT(buf, i + 14); + return info; +} +function readCommon(buf, i) { + var common = {}; + common.lineHeight = buf.readUInt16LE(i); + common.base = buf.readUInt16LE(i + 2); + common.scaleW = buf.readUInt16LE(i + 4); + common.scaleH = buf.readUInt16LE(i + 6); + common.pages = buf.readUInt16LE(i + 8); + var bitField = buf.readUInt8(i + 10); + common.packed = 0; + common.alphaChnl = buf.readUInt8(i + 11); + common.redChnl = buf.readUInt8(i + 12); + common.greenChnl = buf.readUInt8(i + 13); + common.blueChnl = buf.readUInt8(i + 14); + return common; +} +function readPages(buf, i, size) { + var pages = []; + var text = readNameNT(buf, i); + var len = text.length + 1; + var count = size / len; + for (var c = 0; c < count; c++) { + pages[c] = buf.slice(i, i + text.length).toString('utf8'); + i += len; + } + return pages; +} +function readChars(buf, i, blockSize) { + var chars = []; + var count = blockSize / 20; + for (var c = 0; c < count; c++) { + var char = {}; + var off = c * 20; + char.id = buf.readUInt32LE(i + 0 + off); + char.x = buf.readUInt16LE(i + 4 + off); + char.y = buf.readUInt16LE(i + 6 + off); + char.width = buf.readUInt16LE(i + 8 + off); + char.height = buf.readUInt16LE(i + 10 + off); + char.xoffset = buf.readInt16LE(i + 12 + off); + char.yoffset = buf.readInt16LE(i + 14 + off); + char.xadvance = buf.readInt16LE(i + 16 + off); + char.page = buf.readUInt8(i + 18 + off); + char.chnl = buf.readUInt8(i + 19 + off); + chars[c] = char; + } + return chars; +} +function readKernings(buf, i, blockSize) { + var kernings = []; + var count = blockSize / 10; + for (var c = 0; c < count; c++) { + var kern = {}; + var off = c * 10; + kern.first = buf.readUInt32LE(i + 0 + off); + kern.second = buf.readUInt32LE(i + 4 + off); + kern.amount = buf.readInt16LE(i + 8 + off); + kernings[c] = kern; + } + return kernings; +} +function readNameNT(buf, offset) { + var pos = offset; + for (; pos < buf.length; pos++) { + if (buf[pos] === 0x00) break; + } + return buf.slice(offset, pos); +} +function readStringNT(buf, offset) { + return readNameNT(buf, offset).toString('utf8'); +} + +/***/ }), + +/***/ "./node_modules/parse-bmfont-xml/lib/browser.js": +/*!******************************************************!*\ + !*** ./node_modules/parse-bmfont-xml/lib/browser.js ***! + \******************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var parseAttributes = __webpack_require__(/*! ./parse-attribs */ "./node_modules/parse-bmfont-xml/lib/parse-attribs.js"); +var parseFromString = __webpack_require__(/*! xml-parse-from-string */ "./node_modules/xml-parse-from-string/index.js"); + +//In some cases element.attribute.nodeName can return +//all lowercase values.. so we need to map them to the correct +//case +var NAME_MAP = { + scaleh: 'scaleH', + scalew: 'scaleW', + stretchh: 'stretchH', + lineheight: 'lineHeight', + alphachnl: 'alphaChnl', + redchnl: 'redChnl', + greenchnl: 'greenChnl', + bluechnl: 'blueChnl' +}; +module.exports = function parse(data) { + data = data.toString(); + var xmlRoot = parseFromString(data); + var output = { + pages: [], + chars: [], + kernings: [] + } + + //get config settings + ; + ['info', 'common'].forEach(function (key) { + var element = xmlRoot.getElementsByTagName(key)[0]; + if (element) output[key] = parseAttributes(getAttribs(element)); + }); + + //get page info + var pageRoot = xmlRoot.getElementsByTagName('pages')[0]; + if (!pageRoot) throw new Error('malformed file -- no element'); + var pages = pageRoot.getElementsByTagName('page'); + for (var i = 0; i < pages.length; i++) { + var p = pages[i]; + var id = parseInt(p.getAttribute('id'), 10); + var file = p.getAttribute('file'); + if (isNaN(id)) throw new Error('malformed file -- page "id" attribute is NaN'); + if (!file) throw new Error('malformed file -- needs page "file" attribute'); + output.pages[parseInt(id, 10)] = file; + } + + //get kernings / chars + ; + ['chars', 'kernings'].forEach(function (key) { + var element = xmlRoot.getElementsByTagName(key)[0]; + if (!element) return; + var childTag = key.substring(0, key.length - 1); + var children = element.getElementsByTagName(childTag); + for (var i = 0; i < children.length; i++) { + var child = children[i]; + output[key].push(parseAttributes(getAttribs(child))); + } + }); + return output; +}; +function getAttribs(element) { + var attribs = getAttribList(element); + return attribs.reduce(function (dict, attrib) { + var key = mapName(attrib.nodeName); + dict[key] = attrib.nodeValue; + return dict; + }, {}); +} +function getAttribList(element) { + //IE8+ and modern browsers + var attribs = []; + for (var i = 0; i < element.attributes.length; i++) attribs.push(element.attributes[i]); + return attribs; +} +function mapName(nodeName) { + return NAME_MAP[nodeName.toLowerCase()] || nodeName; +} + +/***/ }), + +/***/ "./node_modules/parse-bmfont-xml/lib/parse-attribs.js": +/*!************************************************************!*\ + !*** ./node_modules/parse-bmfont-xml/lib/parse-attribs.js ***! + \************************************************************/ +/***/ ((module) => { + +//Some versions of GlyphDesigner have a typo +//that causes some bugs with parsing. +//Need to confirm with recent version of the software +//to see whether this is still an issue or not. +var GLYPH_DESIGNER_ERROR = 'chasrset'; +module.exports = function parseAttributes(obj) { + if (GLYPH_DESIGNER_ERROR in obj) { + obj['charset'] = obj[GLYPH_DESIGNER_ERROR]; + delete obj[GLYPH_DESIGNER_ERROR]; + } + for (var k in obj) { + if (k === 'face' || k === 'charset') continue;else if (k === 'padding' || k === 'spacing') obj[k] = parseIntList(obj[k]);else obj[k] = parseInt(obj[k], 10); + } + return obj; +}; +function parseIntList(data) { + return data.split(',').map(function (val) { + return parseInt(val, 10); + }); +} + +/***/ }), + +/***/ "./node_modules/parse-headers/parse-headers.js": +/*!*****************************************************!*\ + !*** ./node_modules/parse-headers/parse-headers.js ***! + \*****************************************************/ +/***/ ((module) => { + +var trim = function (string) { + return string.replace(/^\s+|\s+$/g, ''); + }, + isArray = function (arg) { + return Object.prototype.toString.call(arg) === '[object Array]'; + }; +module.exports = function (headers) { + if (!headers) return {}; + var result = {}; + var headersArr = trim(headers).split('\n'); + for (var i = 0; i < headersArr.length; i++) { + var row = headersArr[i]; + var index = row.indexOf(':'), + key = trim(row.slice(0, index)).toLowerCase(), + value = trim(row.slice(index + 1)); + if (typeof result[key] === 'undefined') { + result[key] = value; + } else if (isArray(result[key])) { + result[key].push(value); + } else { + result[key] = [result[key], value]; + } + } + return result; +}; + +/***/ }), + +/***/ "./node_modules/present/lib/present-browser.js": +/*!*****************************************************!*\ + !*** ./node_modules/present/lib/present-browser.js ***! + \*****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var performance = __webpack_require__.g.performance || {}; +var present = function () { + var names = ['now', 'webkitNow', 'msNow', 'mozNow', 'oNow']; + while (names.length) { + var name = names.shift(); + if (name in performance) { + return performance[name].bind(performance); + } + } + var dateNow = Date.now || function () { + return new Date().getTime(); + }; + var navigationStart = (performance.timing || {}).navigationStart || dateNow(); + return function () { + return dateNow() - navigationStart; + }; +}(); +present.performanceNow = performance.now; +present.noConflict = function () { + performance.now = present.performanceNow; +}; +present.conflict = function () { + performance.now = present; +}; +present.conflict(); +module.exports = present; + +/***/ }), + +/***/ "./node_modules/process/browser.js": +/*!*****************************************!*\ + !*** ./node_modules/process/browser.js ***! + \*****************************************/ +/***/ ((module) => { + +// shim for using process in browser +var process = module.exports = {}; + +// cached from whatever global is present so that test runners that stub it +// don't break things. But we need to wrap it in a try catch in case it is +// wrapped in strict mode code which doesn't define any globals. It's inside a +// function because try/catches deoptimize in certain engines. + +var cachedSetTimeout; +var cachedClearTimeout; +function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); +} +function defaultClearTimeout() { + throw new Error('clearTimeout has not been defined'); +} +(function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } +})(); +function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch (e) { + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch (e) { + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } +} +function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e) { + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e) { + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } +} +var queue = []; +var draining = false; +var currentQueue; +var queueIndex = -1; +function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } +} +function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + var len = queue.length; + while (len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); +} +process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; +function noop() {} +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; +process.prependListener = noop; +process.prependOnceListener = noop; +process.listeners = function (name) { + return []; +}; +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; +process.cwd = function () { + return '/'; +}; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function () { + return 0; +}; + +/***/ }), + +/***/ "./node_modules/promise-polyfill/Promise.js": +/*!**************************************************!*\ + !*** ./node_modules/promise-polyfill/Promise.js ***! + \**************************************************/ +/***/ (function(module) { + +(function (root) { + // Store setTimeout reference so promise-polyfill will be unaffected by + // other code modifying setTimeout (like sinon.useFakeTimers()) + var setTimeoutFunc = setTimeout; + + // Use polyfill for setImmediate for performance gains + var asap = typeof setImmediate === 'function' && setImmediate || function (fn) { + setTimeoutFunc(fn, 1); + }; + + // Polyfill for Function.prototype.bind + function bind(fn, thisArg) { + return function () { + fn.apply(thisArg, arguments); + }; + } + var isArray = Array.isArray || function (value) { + return Object.prototype.toString.call(value) === "[object Array]"; + }; + function Promise(fn) { + if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new'); + if (typeof fn !== 'function') throw new TypeError('not a function'); + this._state = null; + this._value = null; + this._deferreds = []; + doResolve(fn, bind(resolve, this), bind(reject, this)); + } + function handle(deferred) { + var me = this; + if (this._state === null) { + this._deferreds.push(deferred); + return; + } + asap(function () { + var cb = me._state ? deferred.onFulfilled : deferred.onRejected; + if (cb === null) { + (me._state ? deferred.resolve : deferred.reject)(me._value); + return; + } + var ret; + try { + ret = cb(me._value); + } catch (e) { + deferred.reject(e); + return; + } + deferred.resolve(ret); + }); + } + function resolve(newValue) { + try { + //Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure + if (newValue === this) throw new TypeError('A promise cannot be resolved with itself.'); + if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) { + var then = newValue.then; + if (typeof then === 'function') { + doResolve(bind(then, newValue), bind(resolve, this), bind(reject, this)); + return; + } + } + this._state = true; + this._value = newValue; + finale.call(this); + } catch (e) { + reject.call(this, e); + } + } + function reject(newValue) { + this._state = false; + this._value = newValue; + finale.call(this); + } + function finale() { + for (var i = 0, len = this._deferreds.length; i < len; i++) { + handle.call(this, this._deferreds[i]); + } + this._deferreds = null; + } + function Handler(onFulfilled, onRejected, resolve, reject) { + this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null; + this.onRejected = typeof onRejected === 'function' ? onRejected : null; + this.resolve = resolve; + this.reject = reject; + } + + /** + * Take a potentially misbehaving resolver function and make sure + * onFulfilled and onRejected are only called once. + * + * Makes no guarantees about asynchrony. + */ + function doResolve(fn, onFulfilled, onRejected) { + var done = false; + try { + fn(function (value) { + if (done) return; + done = true; + onFulfilled(value); + }, function (reason) { + if (done) return; + done = true; + onRejected(reason); + }); + } catch (ex) { + if (done) return; + done = true; + onRejected(ex); + } + } + Promise.prototype['catch'] = function (onRejected) { + return this.then(null, onRejected); + }; + Promise.prototype.then = function (onFulfilled, onRejected) { + var me = this; + return new Promise(function (resolve, reject) { + handle.call(me, new Handler(onFulfilled, onRejected, resolve, reject)); + }); + }; + Promise.all = function () { + var args = Array.prototype.slice.call(arguments.length === 1 && isArray(arguments[0]) ? arguments[0] : arguments); + return new Promise(function (resolve, reject) { + if (args.length === 0) return resolve([]); + var remaining = args.length; + function res(i, val) { + try { + if (val && (typeof val === 'object' || typeof val === 'function')) { + var then = val.then; + if (typeof then === 'function') { + then.call(val, function (val) { + res(i, val); + }, reject); + return; + } + } + args[i] = val; + if (--remaining === 0) { + resolve(args); + } + } catch (ex) { + reject(ex); + } + } + for (var i = 0; i < args.length; i++) { + res(i, args[i]); + } + }); + }; + Promise.resolve = function (value) { + if (value && typeof value === 'object' && value.constructor === Promise) { + return value; + } + return new Promise(function (resolve) { + resolve(value); + }); + }; + Promise.reject = function (value) { + return new Promise(function (resolve, reject) { + reject(value); + }); + }; + Promise.race = function (values) { + return new Promise(function (resolve, reject) { + for (var i = 0, len = values.length; i < len; i++) { + values[i].then(resolve, reject); + } + }); + }; + + /** + * Set the immediate function to execute callbacks + * @param fn {function} Function to execute + * @private + */ + Promise._setImmediateFn = function _setImmediateFn(fn) { + asap = fn; + }; + if ( true && module.exports) { + module.exports = Promise; + } else if (!root.Promise) { + root.Promise = Promise; + } +})(this); + +/***/ }), + +/***/ "./node_modules/quad-indices/index.js": +/*!********************************************!*\ + !*** ./node_modules/quad-indices/index.js ***! + \********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var dtype = __webpack_require__(/*! dtype */ "./node_modules/dtype/index.js"); +var anArray = __webpack_require__(/*! an-array */ "./node_modules/an-array/index.js"); +var isBuffer = __webpack_require__(/*! is-buffer */ "./node_modules/is-buffer/index.js"); +var CW = [0, 2, 3]; +var CCW = [2, 1, 3]; +module.exports = function createQuadElements(array, opt) { + //if user didn't specify an output array + if (!array || !(anArray(array) || isBuffer(array))) { + opt = array || {}; + array = null; + } + if (typeof opt === 'number') + //backwards-compatible + opt = { + count: opt + };else opt = opt || {}; + var type = typeof opt.type === 'string' ? opt.type : 'uint16'; + var count = typeof opt.count === 'number' ? opt.count : 1; + var start = opt.start || 0; + var dir = opt.clockwise !== false ? CW : CCW, + a = dir[0], + b = dir[1], + c = dir[2]; + var numIndices = count * 6; + var indices = array || new (dtype(type))(numIndices); + for (var i = 0, j = 0; i < numIndices; i += 6, j += 4) { + var x = i + start; + indices[x + 0] = j + 0; + indices[x + 1] = j + 1; + indices[x + 2] = j + 2; + indices[x + 3] = j + a; + indices[x + 4] = j + b; + indices[x + 5] = j + c; + } + return indices; +}; + +/***/ }), + +/***/ "./node_modules/super-animejs/lib/anime.es.js": +/*!****************************************************!*\ + !*** ./node_modules/super-animejs/lib/anime.es.js ***! + \****************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) +/* harmony export */ }); +/* + * anime.js v3.0.0 + * (c) 2019 Julian Garnier + * Released under the MIT license + * animejs.com + */ + +// Defaults + +var defaultInstanceSettings = { + update: null, + begin: null, + loopBegin: null, + changeBegin: null, + change: null, + changeComplete: null, + loopComplete: null, + complete: null, + loop: 1, + direction: 'normal', + autoplay: true, + timelineOffset: 0 +}; +var defaultTweenSettings = { + duration: 1000, + delay: 0, + endDelay: 0, + easing: 'easeOutElastic(1, .5)', + round: 0 +}; +var validTransforms = ['translateX', 'translateY', 'translateZ', 'rotate', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scaleX', 'scaleY', 'scaleZ', 'skew', 'skewX', 'skewY', 'perspective']; + +// Caching + +var cache = { + CSS: {}, + springs: {} +}; + +// Utils + +function minMax(val, min, max) { + return Math.min(Math.max(val, min), max); +} +function stringContains(str, text) { + return str.indexOf(text) > -1; +} +function applyArguments(func, args) { + return func.apply(null, args); +} +var hexRegex = /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i; +var rgbPrefixRegex = /^rgb/; +var hslRegex = /^hsl/; +var is = { + arr: function (a) { + return Array.isArray(a); + }, + obj: function (a) { + return stringContains(Object.prototype.toString.call(a), 'Object'); + }, + pth: function (a) { + return is.obj(a) && a.hasOwnProperty('totalLength'); + }, + svg: function (a) { + return a instanceof SVGElement; + }, + inp: function (a) { + return a instanceof HTMLInputElement; + }, + dom: function (a) { + return a.nodeType || is.svg(a); + }, + str: function (a) { + return typeof a === 'string'; + }, + fnc: function (a) { + return typeof a === 'function'; + }, + und: function (a) { + return typeof a === 'undefined'; + }, + hex: function (a) { + return hexRegex.test(a); + }, + rgb: function (a) { + return rgbPrefixRegex.test(a); + }, + hsl: function (a) { + return hslRegex.test(a); + }, + col: function (a) { + return is.hex(a) || is.rgb(a) || is.hsl(a); + }, + key: function (a) { + return !defaultInstanceSettings.hasOwnProperty(a) && !defaultTweenSettings.hasOwnProperty(a) && a !== 'targets' && a !== 'keyframes'; + } +}; + +// Easings + +var easingFunctionRegex = /\(([^)]+)\)/; +function parseEasingParameters(string) { + var match = easingFunctionRegex.exec(string); + return match ? match[1].split(',').map(function (p) { + return parseFloat(p); + }) : []; +} + +// Spring solver inspired by Webkit Copyright © 2016 Apple Inc. All rights reserved. https://webkit.org/demos/spring/spring.js + +function spring(string, duration) { + var params = parseEasingParameters(string); + var mass = minMax(is.und(params[0]) ? 1 : params[0], .1, 100); + var stiffness = minMax(is.und(params[1]) ? 100 : params[1], .1, 100); + var damping = minMax(is.und(params[2]) ? 10 : params[2], .1, 100); + var velocity = minMax(is.und(params[3]) ? 0 : params[3], .1, 100); + var w0 = Math.sqrt(stiffness / mass); + var zeta = damping / (2 * Math.sqrt(stiffness * mass)); + var wd = zeta < 1 ? w0 * Math.sqrt(1 - zeta * zeta) : 0; + var a = 1; + var b = zeta < 1 ? (zeta * w0 + -velocity) / wd : -velocity + w0; + function solver(t) { + var progress = duration ? duration * t / 1000 : t; + if (zeta < 1) { + progress = Math.exp(-progress * zeta * w0) * (a * Math.cos(wd * progress) + b * Math.sin(wd * progress)); + } else { + progress = (a + b * progress) * Math.exp(-progress * w0); + } + if (t === 0 || t === 1) { + return t; + } + return 1 - progress; + } + function getDuration() { + var cached = cache.springs[string]; + if (cached) { + return cached; + } + var frame = 1 / 6; + var elapsed = 0; + var rest = 0; + while (true) { + elapsed += frame; + if (solver(elapsed) === 1) { + rest++; + if (rest >= 16) { + break; + } + } else { + rest = 0; + } + } + var duration = elapsed * frame * 1000; + cache.springs[string] = duration; + return duration; + } + return duration ? solver : getDuration; +} + +// Elastic easing adapted from jQueryUI http://api.jqueryui.com/easings/ + +function elastic(amplitude, period) { + if (amplitude === void 0) amplitude = 1; + if (period === void 0) period = .5; + var a = minMax(amplitude, 1, 10); + var p = minMax(period, .1, 2); + return function (t) { + return t === 0 || t === 1 ? t : -a * Math.pow(2, 10 * (t - 1)) * Math.sin((t - 1 - p / (Math.PI * 2) * Math.asin(1 / a)) * (Math.PI * 2) / p); + }; +} + +// Basic steps easing implementation https://developer.mozilla.org/fr/docs/Web/CSS/transition-timing-function + +function steps(steps) { + if (steps === void 0) steps = 10; + return function (t) { + return Math.round(t * steps) * (1 / steps); + }; +} + +// BezierEasing https://github.com/gre/bezier-easing + +var bezier = function () { + var kSplineTableSize = 11; + var kSampleStepSize = 1.0 / (kSplineTableSize - 1.0); + function A(aA1, aA2) { + return 1.0 - 3.0 * aA2 + 3.0 * aA1; + } + function B(aA1, aA2) { + return 3.0 * aA2 - 6.0 * aA1; + } + function C(aA1) { + return 3.0 * aA1; + } + function calcBezier(aT, aA1, aA2) { + return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT; + } + function getSlope(aT, aA1, aA2) { + return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1); + } + function binarySubdivide(aX, aA, aB, mX1, mX2) { + var currentX, + currentT, + i = 0; + do { + currentT = aA + (aB - aA) / 2.0; + currentX = calcBezier(currentT, mX1, mX2) - aX; + if (currentX > 0.0) { + aB = currentT; + } else { + aA = currentT; + } + } while (Math.abs(currentX) > 0.0000001 && ++i < 10); + return currentT; + } + function newtonRaphsonIterate(aX, aGuessT, mX1, mX2) { + for (var i = 0; i < 4; ++i) { + var currentSlope = getSlope(aGuessT, mX1, mX2); + if (currentSlope === 0.0) { + return aGuessT; + } + var currentX = calcBezier(aGuessT, mX1, mX2) - aX; + aGuessT -= currentX / currentSlope; + } + return aGuessT; + } + function bezier(mX1, mY1, mX2, mY2) { + if (!(0 <= mX1 && mX1 <= 1 && 0 <= mX2 && mX2 <= 1)) { + return; + } + var sampleValues = new Float32Array(kSplineTableSize); + if (mX1 !== mY1 || mX2 !== mY2) { + for (var i = 0; i < kSplineTableSize; ++i) { + sampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2); + } + } + function getTForX(aX) { + var intervalStart = 0; + var currentSample = 1; + var lastSample = kSplineTableSize - 1; + for (; currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample) { + intervalStart += kSampleStepSize; + } + --currentSample; + var dist = (aX - sampleValues[currentSample]) / (sampleValues[currentSample + 1] - sampleValues[currentSample]); + var guessForT = intervalStart + dist * kSampleStepSize; + var initialSlope = getSlope(guessForT, mX1, mX2); + if (initialSlope >= 0.001) { + return newtonRaphsonIterate(aX, guessForT, mX1, mX2); + } else if (initialSlope === 0.0) { + return guessForT; + } else { + return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, mX1, mX2); + } + } + return function (x) { + if (mX1 === mY1 && mX2 === mY2) { + return x; + } + if (x === 0 || x === 1) { + return x; + } + return calcBezier(getTForX(x), mY1, mY2); + }; + } + return bezier; +}(); +var penner = function () { + var names = ['Quad', 'Cubic', 'Quart', 'Quint', 'Sine', 'Expo', 'Circ', 'Back', 'Elastic']; + + // Approximated Penner equations http://matthewlein.com/ceaser/ + + var curves = { + In: [[0.550, 0.085, 0.680, 0.530], /* inQuad */ + [0.550, 0.055, 0.675, 0.190], /* inCubic */ + [0.895, 0.030, 0.685, 0.220], /* inQuart */ + [0.755, 0.050, 0.855, 0.060], /* inQuint */ + [0.470, 0.000, 0.745, 0.715], /* inSine */ + [0.950, 0.050, 0.795, 0.035], /* inExpo */ + [0.600, 0.040, 0.980, 0.335], /* inCirc */ + [0.600, -0.280, 0.735, 0.045], /* inBack */ + elastic /* inElastic */], + + Out: [[0.250, 0.460, 0.450, 0.940], /* outQuad */ + [0.215, 0.610, 0.355, 1.000], /* outCubic */ + [0.165, 0.840, 0.440, 1.000], /* outQuart */ + [0.230, 1.000, 0.320, 1.000], /* outQuint */ + [0.390, 0.575, 0.565, 1.000], /* outSine */ + [0.190, 1.000, 0.220, 1.000], /* outExpo */ + [0.075, 0.820, 0.165, 1.000], /* outCirc */ + [0.175, 0.885, 0.320, 1.275], /* outBack */ + function (a, p) { + return function (t) { + return 1 - elastic(a, p)(1 - t); + }; + } /* outElastic */], + + InOut: [[0.455, 0.030, 0.515, 0.955], /* inOutQuad */ + [0.645, 0.045, 0.355, 1.000], /* inOutCubic */ + [0.770, 0.000, 0.175, 1.000], /* inOutQuart */ + [0.860, 0.000, 0.070, 1.000], /* inOutQuint */ + [0.445, 0.050, 0.550, 0.950], /* inOutSine */ + [1.000, 0.000, 0.000, 1.000], /* inOutExpo */ + [0.785, 0.135, 0.150, 0.860], /* inOutCirc */ + [0.680, -0.550, 0.265, 1.550], /* inOutBack */ + function (a, p) { + return function (t) { + return t < .5 ? elastic(a, p)(t * 2) / 2 : 1 - elastic(a, p)(t * -2 + 2) / 2; + }; + } /* inOutElastic */] + }; + + var eases = { + linear: [0.250, 0.250, 0.750, 0.750] + }; + for (var coords in curves) { + for (var i = 0, len = curves[coords].length; i < len; i++) { + eases['ease' + coords + names[i]] = curves[coords][i]; + } + } + return eases; +}(); +function parseEasings(easing, duration) { + if (is.fnc(easing)) { + return easing; + } + var name = easing.split('(')[0]; + var ease = penner[name]; + var args = parseEasingParameters(easing); + switch (name) { + case 'spring': + return spring(easing, duration); + case 'cubicBezier': + return applyArguments(bezier, args); + case 'steps': + return applyArguments(steps, args); + default: + return is.fnc(ease) ? applyArguments(ease, args) : applyArguments(bezier, ease); + } +} + +// Strings + +function selectString(str) { + try { + var nodes = document.querySelectorAll(str); + return nodes; + } catch (e) { + return; + } +} + +// Arrays + +var auxArrayFilter = []; +function filterArray(arr, callback) { + var result = auxArrayFilter; + var len = arr.length; + var thisArg = arguments.length >= 2 ? arguments[1] : void 0; + for (var i = 0; i < len; i++) { + if (i in arr) { + var val = arr[i]; + if (callback.call(thisArg, val, i, arr)) { + result.push(val); + } + } + } + + // arr turns into the auxArray and we return the previously aux array. + auxArrayFilter = arr; + auxArrayFilter.length = 0; + return result; +} +function flattenArray(arr, result) { + if (!result) { + result = []; + } + for (var i = 0, length = arr.length; i < length; i++) { + var value = arr[i]; + if (Array.isArray(value)) { + flattenArray(value, result); + } else { + result.push(value); + } + } + return result; +} +function toArray(o) { + if (is.arr(o)) { + return o; + } + if (is.str(o)) { + o = selectString(o) || o; + } + if (o instanceof NodeList || o instanceof HTMLCollection) { + return [].slice.call(o); + } + return [o]; +} +function arrayContains(arr, val) { + return arr.some(function (a) { + return a === val; + }); +} + +// Objects + +function cloneObject(o) { + var clone = {}; + for (var p in o) { + clone[p] = o[p]; + } + return clone; +} +function replaceObjectProps(o1, o2) { + var o = cloneObject(o1); + for (var p in o1) { + o[p] = o2.hasOwnProperty(p) ? o2[p] : o1[p]; + } + return o; +} +function mergeObjects(o1, o2) { + var o = cloneObject(o1); + for (var p in o2) { + o[p] = is.und(o1[p]) ? o2[p] : o1[p]; + } + return o; +} + +// Colors + +var rgbRegex = /rgb\((\d+,\s*[\d]+,\s*[\d]+)\)/g; +function rgbToRgba(rgbValue) { + var rgb = rgbRegex.exec(rgbValue); + return rgb ? "rgba(" + rgb[1] + ",1)" : rgbValue; +} +var hexToRgbaHexRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; +var hexToRgbaRgbRegex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i; +function hexToRgba(hexValue) { + var hex = hexValue.replace(hexToRgbaHexRegex, function (m, r, g, b) { + return r + r + g + g + b + b; + }); + var rgb = hexToRgbaRgbRegex.exec(hex); + var r = parseInt(rgb[1], 16); + var g = parseInt(rgb[2], 16); + var b = parseInt(rgb[3], 16); + return "rgba(" + r + "," + g + "," + b + ",1)"; +} +var hslToRgbaHsl1Regex = /hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)/g; +var hslToRgbaHsl2Regex = /hsla\((\d+),\s*([\d.]+)%,\s*([\d.]+)%,\s*([\d.]+)\)/g; +function hslToRgba(hslValue) { + var hsl = hslToRgbaHsl1Regex.exec(hslValue) || hslToRgbaHsl2Regex.exec(hslValue); + var h = parseInt(hsl[1], 10) / 360; + var s = parseInt(hsl[2], 10) / 100; + var l = parseInt(hsl[3], 10) / 100; + var a = hsl[4] || 1; + function hue2rgb(p, q, t) { + if (t < 0) { + t += 1; + } + if (t > 1) { + t -= 1; + } + if (t < 1 / 6) { + return p + (q - p) * 6 * t; + } + if (t < 1 / 2) { + return q; + } + if (t < 2 / 3) { + return p + (q - p) * (2 / 3 - t) * 6; + } + return p; + } + var r, g, b; + if (s == 0) { + r = g = b = l; + } else { + var q = l < 0.5 ? l * (1 + s) : l + s - l * s; + var p = 2 * l - q; + r = hue2rgb(p, q, h + 1 / 3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1 / 3); + } + return "rgba(" + r * 255 + "," + g * 255 + "," + b * 255 + "," + a + ")"; +} +function colorToRgb(val) { + if (is.rgb(val)) { + return rgbToRgba(val); + } + if (is.hex(val)) { + return hexToRgba(val); + } + if (is.hsl(val)) { + return hslToRgba(val); + } +} + +// Units + +var unitRegex = /([\+\-]?[0-9#\.]+)(%|px|pt|em|rem|in|cm|mm|ex|ch|pc|vw|vh|vmin|vmax|deg|rad|turn)?$/; +function getUnit(val) { + var split = unitRegex.exec(val); + if (split) { + return split[2]; + } +} +function getTransformUnit(propName) { + if (stringContains(propName, 'translate') || propName === 'perspective') { + return 'px'; + } + if (stringContains(propName, 'rotate') || stringContains(propName, 'skew')) { + return 'deg'; + } +} + +// Values + +function getFunctionValue(val, animatable) { + if (!is.fnc(val)) { + return val; + } + return val(animatable.target, animatable.id, animatable.total); +} +function getAttribute(el, prop) { + return el.getAttribute(prop); +} +function convertPxToUnit(el, value, unit) { + var valueUnit = getUnit(value); + if (arrayContains([unit, 'deg', 'rad', 'turn'], valueUnit)) { + return value; + } + var cached = cache.CSS[value + unit]; + if (!is.und(cached)) { + return cached; + } + var baseline = 100; + var tempEl = document.createElement(el.tagName); + var parentEl = el.parentNode && el.parentNode !== document ? el.parentNode : document.body; + parentEl.appendChild(tempEl); + tempEl.style.position = 'absolute'; + tempEl.style.width = baseline + unit; + var factor = baseline / tempEl.offsetWidth; + parentEl.removeChild(tempEl); + var convertedUnit = factor * parseFloat(value); + cache.CSS[value + unit] = convertedUnit; + return convertedUnit; +} +function getCSSValue(el, prop, unit) { + if (prop in el.style) { + var uppercasePropName = prop.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); + var value = el.style[prop] || getComputedStyle(el).getPropertyValue(uppercasePropName) || '0'; + return unit ? convertPxToUnit(el, value, unit) : value; + } +} +function getAnimationType(el, prop) { + if (is.dom(el) && !is.inp(el) && (getAttribute(el, prop) || is.svg(el) && el[prop])) { + return 'attribute'; + } + if (is.dom(el) && arrayContains(validTransforms, prop)) { + return 'transform'; + } + if (is.dom(el) && prop !== 'transform' && getCSSValue(el, prop)) { + return 'css'; + } + if (el[prop] != null) { + return 'object'; + } +} +var transformRegex = /(\w+)\(([^)]*)\)/g; +function getElementTransforms(el) { + if (!is.dom(el)) { + return; + } + var str = el.style.transform || ''; + var transforms = new Map(); + var m; + while (m = transformRegex.exec(str)) { + transforms.set(m[1], m[2]); + } + return transforms; +} +function getTransformValue(el, propName, animatable, unit) { + var defaultVal = stringContains(propName, 'scale') ? 1 : 0 + getTransformUnit(propName); + var value = getElementTransforms(el).get(propName) || defaultVal; + if (animatable) { + animatable.transforms.list.set(propName, value); + animatable.transforms['last'] = propName; + } + return unit ? convertPxToUnit(el, value, unit) : value; +} +function getOriginalTargetValue(target, propName, unit, animatable) { + switch (getAnimationType(target, propName)) { + case 'transform': + return getTransformValue(target, propName, animatable, unit); + case 'css': + return getCSSValue(target, propName, unit); + case 'attribute': + return getAttribute(target, propName); + default: + return target[propName] || 0; + } +} +var operatorRegex = /^(\*=|\+=|-=)/; +function getRelativeValue(to, from) { + var operator = operatorRegex.exec(to); + if (!operator) { + return to; + } + var u = getUnit(to) || 0; + var x = parseFloat(from); + var y = parseFloat(to.replace(operator[0], '')); + switch (operator[0][0]) { + case '+': + return x + y + u; + case '-': + return x - y + u; + case '*': + return x * y + u; + } +} +var whitespaceRegex = /\s/g; +function validateValue(val, unit) { + if (is.col(val)) { + return colorToRgb(val); + } + var originalUnit = getUnit(val); + var unitLess = originalUnit ? val.substr(0, val.length - originalUnit.length) : val; + return unit && !whitespaceRegex.test(val) ? unitLess + unit : unitLess; +} + +// getTotalLength() equivalent for circle, rect, polyline, polygon and line shapes +// adapted from https://gist.github.com/SebLambla/3e0550c496c236709744 + +function getDistance(p1, p2) { + return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2)); +} +function getCircleLength(el) { + return Math.PI * 2 * getAttribute(el, 'r'); +} +function getRectLength(el) { + return getAttribute(el, 'width') * 2 + getAttribute(el, 'height') * 2; +} +function getLineLength(el) { + return getDistance({ + x: getAttribute(el, 'x1'), + y: getAttribute(el, 'y1') + }, { + x: getAttribute(el, 'x2'), + y: getAttribute(el, 'y2') + }); +} +function getPolylineLength(el) { + var points = el.points; + var totalLength = 0; + var previousPos; + for (var i = 0; i < points.numberOfItems; i++) { + var currentPos = points.getItem(i); + if (i > 0) { + totalLength += getDistance(previousPos, currentPos); + } + previousPos = currentPos; + } + return totalLength; +} +function getPolygonLength(el) { + var points = el.points; + return getPolylineLength(el) + getDistance(points.getItem(points.numberOfItems - 1), points.getItem(0)); +} + +// Path animation + +function getTotalLength(el) { + if (el.getTotalLength) { + return el.getTotalLength(); + } + switch (el.tagName.toLowerCase()) { + case 'circle': + return getCircleLength(el); + case 'rect': + return getRectLength(el); + case 'line': + return getLineLength(el); + case 'polyline': + return getPolylineLength(el); + case 'polygon': + return getPolygonLength(el); + } +} +function setDashoffset(el) { + var pathLength = getTotalLength(el); + el.setAttribute('stroke-dasharray', pathLength); + return pathLength; +} + +// Motion path + +function getParentSvgEl(el) { + var parentEl = el.parentNode; + while (is.svg(parentEl)) { + parentEl = parentEl.parentNode; + if (!is.svg(parentEl.parentNode)) { + break; + } + } + return parentEl; +} +function getParentSvg(pathEl, svgData) { + var svg = svgData || {}; + var parentSvgEl = svg.el || getParentSvgEl(pathEl); + var rect = parentSvgEl.getBoundingClientRect(); + var viewBoxAttr = getAttribute(parentSvgEl, 'viewBox'); + var width = rect.width; + var height = rect.height; + var viewBox = svg.viewBox || (viewBoxAttr ? viewBoxAttr.split(' ') : [0, 0, width, height]); + return { + el: parentSvgEl, + viewBox: viewBox, + x: viewBox[0] / 1, + y: viewBox[1] / 1, + w: width / viewBox[2], + h: height / viewBox[3] + }; +} +function getPath(path, percent) { + var pathEl = is.str(path) ? selectString(path)[0] : path; + var p = percent || 100; + return function (property) { + return { + property: property, + el: pathEl, + svg: getParentSvg(pathEl), + totalLength: getTotalLength(pathEl) * (p / 100) + }; + }; +} +function getPathProgress(path, progress) { + function point(offset) { + if (offset === void 0) offset = 0; + var l = progress + offset >= 1 ? progress + offset : 0; + return path.el.getPointAtLength(l); + } + var svg = getParentSvg(path.el, path.svg); + var p = point(); + var p0 = point(-1); + var p1 = point(+1); + switch (path.property) { + case 'x': + return (p.x - svg.x) * svg.w; + case 'y': + return (p.y - svg.y) * svg.h; + case 'angle': + return Math.atan2(p1.y - p0.y, p1.x - p0.x) * 180 / Math.PI; + } +} + +// Decompose value + +var valueRegex = /-?\d*\.?\d+/g; +function decomposeValue(val, unit) { + var value = validateValue(is.pth(val) ? val.totalLength : val, unit) + ''; + return { + original: value, + numbers: value.match(valueRegex) ? value.match(valueRegex).map(Number) : [0], + strings: is.str(val) || unit ? value.split(valueRegex) : [] + }; +} + +// Animatables + +function parseTargets(targets) { + var targetsArray = targets ? flattenArray(is.arr(targets) ? targets.map(toArray) : toArray(targets)) : []; + return filterArray(targetsArray, function (item, pos, self) { + return self.indexOf(item) === pos; + }); +} +function getAnimatables(targets) { + var parsed = parseTargets(targets); + return parsed.map(function (t, i) { + return { + target: t, + id: i, + total: parsed.length, + transforms: { + list: getElementTransforms(t) + } + }; + }); +} + +// Properties + +var springRegex = /^spring/; +function normalizePropertyTweens(prop, tweenSettings) { + var settings = cloneObject(tweenSettings); + // Override duration if easing is a spring + if (springRegex.test(settings.easing)) { + settings.duration = spring(settings.easing); + } + if (is.arr(prop)) { + var l = prop.length; + var isFromTo = l === 2 && !is.obj(prop[0]); + if (!isFromTo) { + // Duration divided by the number of tweens + if (!is.fnc(tweenSettings.duration)) { + settings.duration = tweenSettings.duration / l; + } + } else { + // Transform [from, to] values shorthand to a valid tween value + prop = { + value: prop + }; + } + } + var propArray = is.arr(prop) ? prop : [prop]; + return propArray.map(function (v, i) { + var obj = is.obj(v) && !is.pth(v) ? v : { + value: v + }; + // Default delay value should only be applied to the first tween + if (is.und(obj.delay)) { + obj.delay = !i ? tweenSettings.delay : 0; + } + // Default endDelay value should only be applied to the last tween + if (is.und(obj.endDelay)) { + obj.endDelay = i === propArray.length - 1 ? tweenSettings.endDelay : 0; + } + return obj; + }).map(function (k) { + return mergeObjects(k, settings); + }); +} +function flattenKeyframes(keyframes) { + var propertyNames = filterArray(flattenArray(keyframes.map(function (key) { + return Object.keys(key); + })), function (p) { + return is.key(p); + }).reduce(function (a, b) { + if (a.indexOf(b) < 0) { + a.push(b); + } + return a; + }, []); + var properties = {}; + var loop = function (i) { + var propName = propertyNames[i]; + properties[propName] = keyframes.map(function (key) { + var newKey = {}; + for (var p in key) { + if (is.key(p)) { + if (p == propName) { + newKey.value = key[p]; + } + } else { + newKey[p] = key[p]; + } + } + return newKey; + }); + }; + for (var i = 0; i < propertyNames.length; i++) loop(i); + return properties; +} +function getProperties(tweenSettings, params) { + var properties = []; + var keyframes = params.keyframes; + if (keyframes) { + params = mergeObjects(flattenKeyframes(keyframes), params); + } + for (var p in params) { + if (is.key(p)) { + properties.push({ + name: p, + tweens: normalizePropertyTweens(params[p], tweenSettings) + }); + } + } + return properties; +} + +// Tweens + +function normalizeTweenValues(tween, animatable) { + var t = {}; + for (var p in tween) { + var value = getFunctionValue(tween[p], animatable); + if (is.arr(value)) { + value = value.map(function (v) { + return getFunctionValue(v, animatable); + }); + if (value.length === 1) { + value = value[0]; + } + } + t[p] = value; + } + t.duration = parseFloat(t.duration); + t.delay = parseFloat(t.delay); + return t; +} +function normalizeTweens(prop, animatable) { + var previousTween; + return prop.tweens.map(function (t) { + var tween = normalizeTweenValues(t, animatable); + var tweenValue = tween.value; + var to = is.arr(tweenValue) ? tweenValue[1] : tweenValue; + var toUnit = getUnit(to); + var originalValue = getOriginalTargetValue(animatable.target, prop.name, toUnit, animatable); + var previousValue = previousTween ? previousTween.to.original : originalValue; + var from = is.arr(tweenValue) ? tweenValue[0] : previousValue; + var fromUnit = getUnit(from) || getUnit(originalValue); + var unit = toUnit || fromUnit; + if (is.und(to)) { + to = previousValue; + } + tween.from = decomposeValue(from, unit); + tween.to = decomposeValue(getRelativeValue(to, from), unit); + tween.start = previousTween ? previousTween.end : 0; + tween.end = tween.start + tween.delay + tween.duration + tween.endDelay; + tween.easing = parseEasings(tween.easing, tween.duration); + tween.isPath = is.pth(tweenValue); + tween.isColor = is.col(tween.from.original); + if (tween.isColor) { + tween.round = 1; + } + previousTween = tween; + return tween; + }); +} + +// Tween progress + +var setProgressValue = { + css: function (t, p, v) { + return t.style[p] = v; + }, + attribute: function (t, p, v) { + return t.setAttribute(p, v); + }, + object: function (t, p, v) { + return t[p] = v; + }, + transform: function (t, p, v, transforms, manual) { + transforms.list.set(p, v); + if (p === transforms.last || manual) { + var str = ''; + transforms.list.forEach(function (value, prop) { + str += prop + "(" + value + ") "; + }); + t.style.transform = str; + } + } +}; + +// Set Value helper + +function setTargetsValue(targets, properties) { + var animatables = getAnimatables(targets); + for (var i = 0, len = animatables.length; i < len; i++) { + var animatable = animatables[i]; + for (var property in properties) { + var value = getFunctionValue(properties[property], animatable); + var target = animatable.target; + var valueUnit = getUnit(value); + var originalValue = getOriginalTargetValue(target, property, valueUnit, animatable); + var unit = valueUnit || getUnit(originalValue); + var to = getRelativeValue(validateValue(value, unit), originalValue); + var animType = getAnimationType(target, property); + setProgressValue[animType](target, property, to, animatable.transforms, true); + } + } +} + +// Animations + +function createAnimation(animatable, prop) { + var animType = getAnimationType(animatable.target, prop.name); + if (animType) { + var tweens = normalizeTweens(prop, animatable); + var lastTween = tweens[tweens.length - 1]; + return { + type: animType, + property: prop.name, + animatable: animatable, + tweens: tweens, + duration: lastTween.end, + delay: tweens[0].delay, + endDelay: lastTween.endDelay + }; + } +} +function getAnimations(animatables, properties) { + return filterArray(flattenArray(animatables.map(function (animatable) { + return properties.map(function (prop) { + return createAnimation(animatable, prop); + }); + })), function (a) { + return !is.und(a); + }); +} + +// Create Instance + +function getInstanceTimings(animations, tweenSettings) { + var animLength = animations.length; + var getTlOffset = function (anim) { + return anim.timelineOffset ? anim.timelineOffset : 0; + }; + var timings = {}; + timings.duration = animLength ? Math.max.apply(Math, animations.map(function (anim) { + return getTlOffset(anim) + anim.duration; + })) : tweenSettings.duration; + timings.delay = animLength ? Math.min.apply(Math, animations.map(function (anim) { + return getTlOffset(anim) + anim.delay; + })) : tweenSettings.delay; + timings.endDelay = animLength ? timings.duration - Math.max.apply(Math, animations.map(function (anim) { + return getTlOffset(anim) + anim.duration - anim.endDelay; + })) : tweenSettings.endDelay; + return timings; +} +var instanceID = 0; +function createNewInstance(params) { + var instanceSettings = replaceObjectProps(defaultInstanceSettings, params); + var tweenSettings = replaceObjectProps(defaultTweenSettings, params); + var properties = getProperties(tweenSettings, params); + var animatables = getAnimatables(params.targets); + var animations = getAnimations(animatables, properties); + var timings = getInstanceTimings(animations, tweenSettings); + var id = instanceID; + instanceID++; + return mergeObjects(instanceSettings, { + id: id, + children: [], + animatables: animatables, + animations: animations, + duration: timings.duration, + delay: timings.delay, + endDelay: timings.endDelay + }); +} + +// Core + +var activeInstances = []; +var pausedInstances = []; +var raf; +var engine = function () { + function play() { + raf = requestAnimationFrame(step); + } + function step(t) { + var activeInstancesLength = activeInstances.length; + if (activeInstancesLength) { + var i = 0; + while (i < activeInstancesLength) { + var activeInstance = activeInstances[i]; + if (!activeInstance.paused) { + activeInstance.tick(t); + } else { + var instanceIndex = activeInstances.indexOf(activeInstance); + if (instanceIndex > -1) { + activeInstances.splice(instanceIndex, 1); + activeInstancesLength = activeInstances.length; + } + } + i++; + } + play(); + } else { + raf = cancelAnimationFrame(raf); + } + } + return play; +}(); +function handleVisibilityChange() { + if (document.hidden) { + for (var i = 0, len = activeInstances.length; i < len; i++) { + activeInstance[i].pause(); + } + pausedInstances = activeInstances.slice(0); + activeInstances = []; + } else { + for (var i$1 = 0, len$1 = pausedInstances.length; i$1 < len$1; i$1++) { + pausedInstances[i$1].play(); + } + } +} +document.addEventListener('visibilitychange', handleVisibilityChange); + +// Public Instance + +function anime(params) { + if (params === void 0) params = {}; + var startTime = 0, + lastTime = 0, + now = 0; + var children, + childrenLength = 0; + var resolve = null; + function makePromise() { + return window.Promise && new Promise(function (_resolve) { + return resolve = _resolve; + }); + } + var promise = makePromise(); + var instance = createNewInstance(params); + function toggleInstanceDirection() { + instance.reversed = !instance.reversed; + for (var i = 0, len = children.length; i < len; i++) { + children[i].reversed = instance.reversed; + } + } + function adjustTime(time) { + return instance.reversed ? instance.duration - time : time; + } + function resetTime() { + startTime = 0; + lastTime = adjustTime(instance.currentTime) * (1 / anime.speed); + } + function seekCild(time, child) { + if (child) { + child.seek(time - child.timelineOffset); + } + } + function syncInstanceChildren(time) { + if (!instance.reversePlayback) { + for (var i = 0; i < childrenLength; i++) { + seekCild(time, children[i]); + } + } else { + for (var i$1 = childrenLength; i$1--;) { + seekCild(time, children[i$1]); + } + } + } + function setAnimationsProgress(insTime) { + var i = 0; + var animations = instance.animations; + var animationsLength = animations.length; + while (i < animationsLength) { + var anim = animations[i]; + var animatable = anim.animatable; + var tweens = anim.tweens; + var tweenLength = tweens.length - 1; + var tween = tweens[tweenLength]; + // Only check for keyframes if there is more than one tween + if (tweenLength) { + tween = filterArray(tweens, function (t) { + return insTime < t.end; + })[0] || tween; + } + var elapsed = minMax(insTime - tween.start - tween.delay, 0, tween.duration) / tween.duration; + var eased = isNaN(elapsed) ? 1 : tween.easing(elapsed); + var strings = tween.to.strings; + var round = tween.round; + var numbers = []; + var toNumbersLength = tween.to.numbers.length; + var progress = void 0; + for (var n = 0; n < toNumbersLength; n++) { + var value = void 0; + var toNumber = tween.to.numbers[n]; + var fromNumber = tween.from.numbers[n] || 0; + if (!tween.isPath) { + value = fromNumber + eased * (toNumber - fromNumber); + } else { + value = getPathProgress(tween.value, eased * toNumber); + } + if (round) { + if (!(tween.isColor && n > 2)) { + value = Math.round(value * round) / round; + } + } + numbers.push(value); + } + // Manual Array.reduce for better performances + var stringsLength = strings.length; + if (!stringsLength) { + progress = numbers[0]; + } else { + progress = strings[0]; + for (var s = 0; s < stringsLength; s++) { + var a = strings[s]; + var b = strings[s + 1]; + var n$1 = numbers[s]; + if (!isNaN(n$1)) { + if (!b) { + progress += n$1 + ' '; + } else { + progress += n$1 + b; + } + } + } + } + setProgressValue[anim.type](animatable.target, anim.property, progress, animatable.transforms); + anim.currentValue = progress; + i++; + } + } + function setCallback(cb) { + if (instance[cb] && !instance.passThrough) { + instance[cb](instance); + } + } + function countIteration() { + if (instance.remaining && instance.remaining !== true) { + instance.remaining--; + } + } + function setInstanceProgress(engineTime) { + var insDuration = instance.duration; + var insDelay = instance.delay; + var insEndDelay = insDuration - instance.endDelay; + var insTime = adjustTime(engineTime); + instance.progress = minMax(insTime / insDuration * 100, 0, 100); + instance.reversePlayback = insTime < instance.currentTime; + if (children) { + syncInstanceChildren(insTime); + } + if (!instance.began && instance.currentTime > 0) { + instance.began = true; + setCallback('begin'); + setCallback('loopBegin'); + } + if (insTime <= insDelay && instance.currentTime !== 0) { + setAnimationsProgress(0); + } + if (insTime >= insEndDelay && instance.currentTime !== insDuration || !insDuration) { + setAnimationsProgress(insDuration); + } + if (insTime > insDelay && insTime < insEndDelay) { + if (!instance.changeBegan) { + instance.changeBegan = true; + instance.changeCompleted = false; + setCallback('changeBegin'); + } + setCallback('change'); + setAnimationsProgress(insTime); + } else { + if (instance.changeBegan) { + instance.changeCompleted = true; + instance.changeBegan = false; + setCallback('changeComplete'); + } + } + instance.currentTime = minMax(insTime, 0, insDuration); + if (instance.began) { + setCallback('update'); + } + if (engineTime >= insDuration) { + lastTime = 0; + countIteration(); + if (instance.remaining) { + startTime = now; + setCallback('loopComplete'); + setCallback('loopBegin'); + if (instance.direction === 'alternate') { + toggleInstanceDirection(); + } + } else { + instance.paused = true; + if (!instance.completed) { + instance.completed = true; + setCallback('loopComplete'); + setCallback('complete'); + if ('Promise' in window) { + resolve(); + promise = makePromise(); + } + } + } + } + } + instance.reset = function () { + var direction = instance.direction; + instance.passThrough = false; + instance.currentTime = 0; + instance.progress = 0; + instance.paused = true; + instance.began = false; + instance.changeBegan = false; + instance.completed = false; + instance.changeCompleted = false; + instance.reversePlayback = false; + instance.reversed = direction === 'reverse'; + instance.remaining = instance.loop; + children = instance.children; + childrenLength = children.length; + for (var i = childrenLength; i--;) { + instance.children[i].reset(); + } + if (instance.reversed && instance.loop !== true || direction === 'alternate' && instance.loop === 1) { + instance.remaining++; + } + setAnimationsProgress(0); + }; + + // Set Value helper + + instance.set = function (targets, properties) { + setTargetsValue(targets, properties); + return instance; + }; + instance.tick = function (t) { + now = t; + if (!startTime) { + startTime = now; + } + setInstanceProgress((now + (lastTime - startTime)) * anime.speed); + }; + instance.seek = function (time) { + setInstanceProgress(adjustTime(time)); + }; + instance.pause = function () { + instance.paused = true; + resetTime(); + }; + instance.play = function () { + if (!instance.paused) { + return; + } + instance.paused = false; + activeInstances.push(instance); + resetTime(); + if (!raf) { + engine(); + } + }; + instance.reverse = function () { + toggleInstanceDirection(); + resetTime(); + }; + instance.restart = function () { + instance.reset(); + instance.play(); + }; + instance.finished = promise; + instance.reset(); + if (instance.autoplay) { + instance.play(); + } + return instance; +} + +// Remove targets from animation + +function removeTargetsFromAnimations(targetsArray, animations) { + for (var a = animations.length; a--;) { + if (arrayContains(targetsArray, animations[a].animatable.target)) { + animations.splice(a, 1); + } + } +} +function removeTargets(targets) { + var targetsArray = parseTargets(targets); + for (var i = activeInstances.length; i--;) { + var instance = activeInstances[i]; + var animations = instance.animations; + var children = instance.children; + removeTargetsFromAnimations(targetsArray, animations); + for (var c = children.length; c--;) { + var child = children[c]; + var childAnimations = child.animations; + removeTargetsFromAnimations(targetsArray, childAnimations); + if (!childAnimations.length && !child.children.length) { + children.splice(c, 1); + } + } + if (!animations.length && !children.length) { + instance.pause(); + } + } +} + +// Stagger helpers + +function stagger(val, params) { + if (params === void 0) params = {}; + var direction = params.direction || 'normal'; + var easing = params.easing ? parseEasings(params.easing) : null; + var grid = params.grid; + var axis = params.axis; + var fromIndex = params.from || 0; + var fromFirst = fromIndex === 'first'; + var fromCenter = fromIndex === 'center'; + var fromLast = fromIndex === 'last'; + var isRange = is.arr(val); + var val1 = isRange ? parseFloat(val[0]) : parseFloat(val); + var val2 = isRange ? parseFloat(val[1]) : 0; + var unit = getUnit(isRange ? val[1] : val) || 0; + var start = params.start || 0 + (isRange ? val1 : 0); + var values = []; + var maxValue = 0; + return function (el, i, t) { + if (fromFirst) { + fromIndex = 0; + } + if (fromCenter) { + fromIndex = (t - 1) / 2; + } + if (fromLast) { + fromIndex = t - 1; + } + if (!values.length) { + for (var index = 0; index < t; index++) { + if (!grid) { + values.push(Math.abs(fromIndex - index)); + } else { + var fromX = !fromCenter ? fromIndex % grid[0] : (grid[0] - 1) / 2; + var fromY = !fromCenter ? Math.floor(fromIndex / grid[0]) : (grid[1] - 1) / 2; + var toX = index % grid[0]; + var toY = Math.floor(index / grid[0]); + var distanceX = fromX - toX; + var distanceY = fromY - toY; + var value = Math.sqrt(distanceX * distanceX + distanceY * distanceY); + if (axis === 'x') { + value = -distanceX; + } + if (axis === 'y') { + value = -distanceY; + } + values.push(value); + } + maxValue = Math.max.apply(Math, values); + } + if (easing) { + values = values.map(function (val) { + return easing(val / maxValue) * maxValue; + }); + } + if (direction === 'reverse') { + values = values.map(function (val) { + return axis ? val < 0 ? val * -1 : -val : Math.abs(maxValue - val); + }); + } + } + var spacing = isRange ? (val2 - val1) / maxValue : val1; + return start + spacing * (Math.round(values[i] * 100) / 100) + unit; + }; +} + +// Timeline + +function timeline(params) { + if (params === void 0) params = {}; + var tl = anime(params); + tl.duration = 0; + tl.add = function (instanceParams, timelineOffset) { + var tlIndex = activeInstances.indexOf(tl); + var children = tl.children; + if (tlIndex > -1) { + activeInstances.splice(tlIndex, 1); + } + function passThrough(ins) { + ins.passThrough = true; + } + for (var i = 0; i < children.length; i++) { + passThrough(children[i]); + } + var insParams = mergeObjects(instanceParams, replaceObjectProps(defaultTweenSettings, params)); + insParams.targets = insParams.targets || params.targets; + var tlDuration = tl.duration; + insParams.autoplay = false; + insParams.direction = tl.direction; + insParams.timelineOffset = is.und(timelineOffset) ? tlDuration : getRelativeValue(timelineOffset, tlDuration); + passThrough(tl); + tl.seek(insParams.timelineOffset); + var ins = anime(insParams); + passThrough(ins); + children.push(ins); + var timings = getInstanceTimings(children, params); + tl.delay = timings.delay; + tl.endDelay = timings.endDelay; + tl.duration = timings.duration; + tl.seek(0); + tl.reset(); + if (tl.autoplay) { + tl.play(); + } + return tl; + }; + return tl; +} +anime.version = '3.0.0'; +anime.speed = 1; +anime.running = activeInstances; +anime.remove = removeTargets; +anime.get = getOriginalTargetValue; +anime.set = setTargetsValue; +anime.convertPx = convertPxToUnit; +anime.path = getPath; +anime.setDashoffset = setDashoffset; +anime.stagger = stagger; +anime.timeline = timeline; +anime.easing = parseEasings; +anime.penner = penner; +anime.random = function (min, max) { + return Math.floor(Math.random() * (max - min + 1)) + min; +}; +/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (anime); + +/***/ }), + +/***/ "./node_modules/three-bmfont-text/index.js": +/*!*************************************************!*\ + !*** ./node_modules/three-bmfont-text/index.js ***! + \*************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var createLayout = __webpack_require__(/*! layout-bmfont-text */ "./node_modules/layout-bmfont-text/index.js"); +var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js"); +var createIndices = __webpack_require__(/*! quad-indices */ "./node_modules/quad-indices/index.js"); +var buffer = __webpack_require__(/*! three-buffer-vertex-data */ "./node_modules/three-buffer-vertex-data/index.js"); +var assign = __webpack_require__(/*! object-assign */ "./node_modules/object-assign/index.js"); +var vertices = __webpack_require__(/*! ./lib/vertices */ "./node_modules/three-bmfont-text/lib/vertices.js"); +var utils = __webpack_require__(/*! ./lib/utils */ "./node_modules/three-bmfont-text/lib/utils.js"); +module.exports = function createTextGeometry(opt) { + return new TextGeometry(opt); +}; +class TextGeometry extends THREE.BufferGeometry { + constructor(opt) { + super(); + if (typeof opt === 'string') { + opt = { + text: opt + }; + } + + // use these as default values for any subsequent + // calls to update() + this._opt = assign({}, opt); + + // also do an initial setup... + if (opt) this.update(opt); + } + update(opt) { + if (typeof opt === 'string') { + opt = { + text: opt + }; + } + + // use constructor defaults + opt = assign({}, this._opt, opt); + if (!opt.font) { + throw new TypeError('must specify a { font } in options'); + } + this.layout = createLayout(opt); + + // get vec2 texcoords + var flipY = opt.flipY !== false; + + // the desired BMFont data + var font = opt.font; + + // determine texture size from font file + var texWidth = font.common.scaleW; + var texHeight = font.common.scaleH; + + // get visible glyphs + var glyphs = this.layout.glyphs.filter(function (glyph) { + var bitmap = glyph.data; + return bitmap.width * bitmap.height > 0; + }); + + // provide visible glyphs for convenience + this.visibleGlyphs = glyphs; + + // get common vertex data + var positions = vertices.positions(glyphs); + var uvs = vertices.uvs(glyphs, texWidth, texHeight, flipY); + var indices = createIndices({ + clockwise: true, + type: 'uint16', + count: glyphs.length + }); + + // update vertex data + buffer.index(this, indices, 1, 'uint16'); + buffer.attr(this, 'position', positions, 2); + buffer.attr(this, 'uv', uvs, 2); + + // update multipage data + if (!opt.multipage && 'page' in this.attributes) { + // disable multipage rendering + this.removeAttribute('page'); + } else if (opt.multipage) { + var pages = vertices.pages(glyphs); + // enable multipage rendering + buffer.attr(this, 'page', pages, 1); + } + } + computeBoundingSphere() { + if (this.boundingSphere === null) { + this.boundingSphere = new THREE.Sphere(); + } + var positions = this.attributes.position.array; + var itemSize = this.attributes.position.itemSize; + if (!positions || !itemSize || positions.length < 2) { + this.boundingSphere.radius = 0; + this.boundingSphere.center.set(0, 0, 0); + return; + } + utils.computeSphere(positions, this.boundingSphere); + if (isNaN(this.boundingSphere.radius)) { + console.error('THREE.BufferGeometry.computeBoundingSphere(): ' + 'Computed radius is NaN. The ' + '"position" attribute is likely to have NaN values.'); + } + } + computeBoundingBox() { + if (this.boundingBox === null) { + this.boundingBox = new THREE.Box3(); + } + var bbox = this.boundingBox; + var positions = this.attributes.position.array; + var itemSize = this.attributes.position.itemSize; + if (!positions || !itemSize || positions.length < 2) { + bbox.makeEmpty(); + return; + } + utils.computeBox(positions, bbox); + } +} + +/***/ }), + +/***/ "./node_modules/three-bmfont-text/lib/utils.js": +/*!*****************************************************!*\ + !*** ./node_modules/three-bmfont-text/lib/utils.js ***! + \*****************************************************/ +/***/ ((module) => { + +var itemSize = 2; +var box = { + min: [0, 0], + max: [0, 0] +}; +function bounds(positions) { + var count = positions.length / itemSize; + box.min[0] = positions[0]; + box.min[1] = positions[1]; + box.max[0] = positions[0]; + box.max[1] = positions[1]; + for (var i = 0; i < count; i++) { + var x = positions[i * itemSize + 0]; + var y = positions[i * itemSize + 1]; + box.min[0] = Math.min(x, box.min[0]); + box.min[1] = Math.min(y, box.min[1]); + box.max[0] = Math.max(x, box.max[0]); + box.max[1] = Math.max(y, box.max[1]); + } +} +module.exports.computeBox = function (positions, output) { + bounds(positions); + output.min.set(box.min[0], box.min[1], 0); + output.max.set(box.max[0], box.max[1], 0); +}; +module.exports.computeSphere = function (positions, output) { + bounds(positions); + var minX = box.min[0]; + var minY = box.min[1]; + var maxX = box.max[0]; + var maxY = box.max[1]; + var width = maxX - minX; + var height = maxY - minY; + var length = Math.sqrt(width * width + height * height); + output.center.set(minX + width / 2, minY + height / 2, 0); + output.radius = length / 2; +}; + +/***/ }), + +/***/ "./node_modules/three-bmfont-text/lib/vertices.js": +/*!********************************************************!*\ + !*** ./node_modules/three-bmfont-text/lib/vertices.js ***! + \********************************************************/ +/***/ ((module) => { + +module.exports.pages = function pages(glyphs) { + var pages = new Float32Array(glyphs.length * 4 * 1); + var i = 0; + glyphs.forEach(function (glyph) { + var id = glyph.data.page || 0; + pages[i++] = id; + pages[i++] = id; + pages[i++] = id; + pages[i++] = id; + }); + return pages; +}; +module.exports.uvs = function uvs(glyphs, texWidth, texHeight, flipY) { + var uvs = new Float32Array(glyphs.length * 4 * 2); + var i = 0; + glyphs.forEach(function (glyph) { + var bitmap = glyph.data; + var bw = bitmap.x + bitmap.width; + var bh = bitmap.y + bitmap.height; + + // top left position + var u0 = bitmap.x / texWidth; + var v1 = bitmap.y / texHeight; + var u1 = bw / texWidth; + var v0 = bh / texHeight; + if (flipY) { + v1 = (texHeight - bitmap.y) / texHeight; + v0 = (texHeight - bh) / texHeight; + } + + // BL + uvs[i++] = u0; + uvs[i++] = v1; + // TL + uvs[i++] = u0; + uvs[i++] = v0; + // TR + uvs[i++] = u1; + uvs[i++] = v0; + // BR + uvs[i++] = u1; + uvs[i++] = v1; + }); + return uvs; +}; +module.exports.positions = function positions(glyphs) { + var positions = new Float32Array(glyphs.length * 4 * 2); + var i = 0; + glyphs.forEach(function (glyph) { + var bitmap = glyph.data; + + // bottom left position + var x = glyph.position[0] + bitmap.xoffset; + var y = glyph.position[1] + bitmap.yoffset; + + // quad size + var w = bitmap.width; + var h = bitmap.height; + + // BL + positions[i++] = x; + positions[i++] = y; + // TL + positions[i++] = x; + positions[i++] = y + h; + // TR + positions[i++] = x + w; + positions[i++] = y + h; + // BR + positions[i++] = x + w; + positions[i++] = y; + }); + return positions; +}; + +/***/ }), + +/***/ "./node_modules/three-buffer-vertex-data/index.js": +/*!********************************************************!*\ + !*** ./node_modules/three-buffer-vertex-data/index.js ***! + \********************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var flatten = __webpack_require__(/*! flatten-vertex-data */ "./node_modules/flatten-vertex-data/index.js"); +var warned = false; +module.exports.attr = setAttribute; +module.exports.index = setIndex; +function setIndex(geometry, data, itemSize, dtype) { + if (typeof itemSize !== 'number') itemSize = 1; + if (typeof dtype !== 'string') dtype = 'uint16'; + var isR69 = !geometry.index && typeof geometry.setIndex !== 'function'; + var attrib = isR69 ? geometry.getAttribute('index') : geometry.index; + var newAttrib = updateAttribute(attrib, data, itemSize, dtype); + if (newAttrib) { + if (isR69) geometry.addAttribute('index', newAttrib);else geometry.index = newAttrib; + } +} +function setAttribute(geometry, key, data, itemSize, dtype) { + if (typeof itemSize !== 'number') itemSize = 3; + if (typeof dtype !== 'string') dtype = 'float32'; + if (Array.isArray(data) && Array.isArray(data[0]) && data[0].length !== itemSize) { + throw new Error('Nested vertex array has unexpected size; expected ' + itemSize + ' but found ' + data[0].length); + } + var attrib = geometry.getAttribute(key); + var newAttrib = updateAttribute(attrib, data, itemSize, dtype); + geometry.setAttribute(key, newAttrib); +} +function updateAttribute(attrib, data, itemSize, dtype) { + data = data || []; + + // create a new array with desired type + data = flatten(data, dtype); + attrib = new THREE.BufferAttribute(data, itemSize); + attrib.itemSize = itemSize; + attrib.needsUpdate = true; + return attrib; +} + +// Test whether the attribute needs to be re-created, +// returns false if we can re-use it as-is. +function rebuildAttribute(attrib, data, itemSize) { + if (attrib.itemSize !== itemSize) return true; + if (!attrib.array) return true; + var attribLength = attrib.array.length; + if (Array.isArray(data) && Array.isArray(data[0])) { + // [ [ x, y, z ] ] + return attribLength !== data.length * itemSize; + } else { + // [ x, y, z ] + return attribLength !== data.length; + } + return false; +} + +/***/ }), + +/***/ "./node_modules/webvr-polyfill/build/webvr-polyfill.js": +/*!*************************************************************!*\ + !*** ./node_modules/webvr-polyfill/build/webvr-polyfill.js ***! + \*************************************************************/ +/***/ (function(module, __unused_webpack_exports, __webpack_require__) { + +/** + * @license + * webvr-polyfill + * Copyright (c) 2015-2017 Google + * 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. + */ + +/** + * @license + * cardboard-vr-display + * Copyright (c) 2015-2017 Google + * 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. + */ + +/** + * @license + * webvr-polyfill-dpdb + * Copyright (c) 2017 Google + * 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. + */ + +/** + * @license + * wglu-preserve-state + * Copyright (c) 2016, Brandon Jones. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * @license + * nosleep.js + * Copyright (c) 2017, Rich Tibbett + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +(function (global, factory) { + true ? module.exports = factory() : 0; +})(this, function () { + 'use strict'; + + var commonjsGlobal = typeof window !== 'undefined' ? window : typeof __webpack_require__.g !== 'undefined' ? __webpack_require__.g : typeof self !== 'undefined' ? self : {}; + function unwrapExports(x) { + return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; + } + function createCommonjsModule(fn, module) { + return module = { + exports: {} + }, fn(module, module.exports), module.exports; + } + var isMobile = function isMobile() { + return /Android/i.test(navigator.userAgent) || /iPhone|iPad|iPod/i.test(navigator.userAgent); + }; + var copyArray = function copyArray(source, dest) { + for (var i = 0, n = source.length; i < n; i++) { + dest[i] = source[i]; + } + }; + var extend = function extend(dest, src) { + for (var key in src) { + if (src.hasOwnProperty(key)) { + dest[key] = src[key]; + } + } + return dest; + }; + var cardboardVrDisplay = createCommonjsModule(function (module, exports) { + /** + * @license + * cardboard-vr-display + * Copyright (c) 2015-2017 Google + * 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. + */ + /** + * @license + * gl-preserve-state + * Copyright (c) 2016, Brandon Jones. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + /** + * @license + * webvr-polyfill-dpdb + * Copyright (c) 2015-2017 Google + * 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. + */ + /** + * @license + * nosleep.js + * Copyright (c) 2017, Rich Tibbett + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + (function (global, factory) { + module.exports = factory(); + })(commonjsGlobal, function () { + var classCallCheck = function (instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + }; + var createClass = function () { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function (Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + var slicedToArray = function () { + function sliceIterator(arr, i) { + var _arr = []; + var _n = true; + var _d = false; + var _e = undefined; + try { + for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { + _arr.push(_s.value); + if (i && _arr.length === i) break; + } + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i["return"]) _i["return"](); + } finally { + if (_d) throw _e; + } + } + return _arr; + } + return function (arr, i) { + if (Array.isArray(arr)) { + return arr; + } else if (Symbol.iterator in Object(arr)) { + return sliceIterator(arr, i); + } else { + throw new TypeError("Invalid attempt to destructure non-iterable instance"); + } + }; + }(); + var MIN_TIMESTEP = 0.001; + var MAX_TIMESTEP = 1; + var dataUri = function dataUri(mimeType, svg) { + return 'data:' + mimeType + ',' + encodeURIComponent(svg); + }; + var lerp = function lerp(a, b, t) { + return a + (b - a) * t; + }; + var isIOS = function () { + var isIOS = /iPad|iPhone|iPod/.test(navigator.platform); + return function () { + return isIOS; + }; + }(); + var isWebViewAndroid = function () { + var isWebViewAndroid = navigator.userAgent.indexOf('Version') !== -1 && navigator.userAgent.indexOf('Android') !== -1 && navigator.userAgent.indexOf('Chrome') !== -1; + return function () { + return isWebViewAndroid; + }; + }(); + var isSafari = function () { + var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); + return function () { + return isSafari; + }; + }(); + var isFirefoxAndroid = function () { + var isFirefoxAndroid = navigator.userAgent.indexOf('Firefox') !== -1 && navigator.userAgent.indexOf('Android') !== -1; + return function () { + return isFirefoxAndroid; + }; + }(); + var getChromeVersion = function () { + var match = navigator.userAgent.match(/.*Chrome\/([0-9]+)/); + var value = match ? parseInt(match[1], 10) : null; + return function () { + return value; + }; + }(); + var isSafariWithoutDeviceMotion = function () { + var value = false; + value = isIOS() && isSafari() && navigator.userAgent.indexOf('13_4') !== -1; + return function () { + return value; + }; + }(); + var isChromeWithoutDeviceMotion = function () { + var value = false; + if (getChromeVersion() === 65) { + var match = navigator.userAgent.match(/.*Chrome\/([0-9\.]*)/); + if (match) { + var _match$1$split = match[1].split('.'), + _match$1$split2 = slicedToArray(_match$1$split, 4), + major = _match$1$split2[0], + minor = _match$1$split2[1], + branch = _match$1$split2[2], + build = _match$1$split2[3]; + value = parseInt(branch, 10) === 3325 && parseInt(build, 10) < 148; + } + } + return function () { + return value; + }; + }(); + var isR7 = function () { + var isR7 = navigator.userAgent.indexOf('R7 Build') !== -1; + return function () { + return isR7; + }; + }(); + var isLandscapeMode = function isLandscapeMode() { + var rtn = window.orientation == 90 || window.orientation == -90; + return isR7() ? !rtn : rtn; + }; + var isTimestampDeltaValid = function isTimestampDeltaValid(timestampDeltaS) { + if (isNaN(timestampDeltaS)) { + return false; + } + if (timestampDeltaS <= MIN_TIMESTEP) { + return false; + } + if (timestampDeltaS > MAX_TIMESTEP) { + return false; + } + return true; + }; + var getScreenWidth = function getScreenWidth() { + return Math.max(window.screen.width, window.screen.height) * window.devicePixelRatio; + }; + var getScreenHeight = function getScreenHeight() { + return Math.min(window.screen.width, window.screen.height) * window.devicePixelRatio; + }; + var requestFullscreen = function requestFullscreen(element) { + if (isWebViewAndroid()) { + return false; + } + if (element.requestFullscreen) { + element.requestFullscreen(); + } else if (element.webkitRequestFullscreen) { + element.webkitRequestFullscreen(); + } else if (element.mozRequestFullScreen) { + element.mozRequestFullScreen(); + } else if (element.msRequestFullscreen) { + element.msRequestFullscreen(); + } else { + return false; + } + return true; + }; + var exitFullscreen = function exitFullscreen() { + if (document.exitFullscreen) { + document.exitFullscreen(); + } else if (document.webkitExitFullscreen) { + document.webkitExitFullscreen(); + } else if (document.mozCancelFullScreen) { + document.mozCancelFullScreen(); + } else if (document.msExitFullscreen) { + document.msExitFullscreen(); + } else { + return false; + } + return true; + }; + var getFullscreenElement = function getFullscreenElement() { + return document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement; + }; + var linkProgram = function linkProgram(gl, vertexSource, fragmentSource, attribLocationMap) { + var vertexShader = gl.createShader(gl.VERTEX_SHADER); + gl.shaderSource(vertexShader, vertexSource); + gl.compileShader(vertexShader); + var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); + gl.shaderSource(fragmentShader, fragmentSource); + gl.compileShader(fragmentShader); + var program = gl.createProgram(); + gl.attachShader(program, vertexShader); + gl.attachShader(program, fragmentShader); + for (var attribName in attribLocationMap) { + gl.bindAttribLocation(program, attribLocationMap[attribName], attribName); + } + gl.linkProgram(program); + gl.deleteShader(vertexShader); + gl.deleteShader(fragmentShader); + return program; + }; + var getProgramUniforms = function getProgramUniforms(gl, program) { + var uniforms = {}; + var uniformCount = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS); + var uniformName = ''; + for (var i = 0; i < uniformCount; i++) { + var uniformInfo = gl.getActiveUniform(program, i); + uniformName = uniformInfo.name.replace('[0]', ''); + uniforms[uniformName] = gl.getUniformLocation(program, uniformName); + } + return uniforms; + }; + var orthoMatrix = function orthoMatrix(out, left, right, bottom, top, near, far) { + var lr = 1 / (left - right), + bt = 1 / (bottom - top), + nf = 1 / (near - far); + out[0] = -2 * lr; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 0; + out[5] = -2 * bt; + out[6] = 0; + out[7] = 0; + out[8] = 0; + out[9] = 0; + out[10] = 2 * nf; + out[11] = 0; + out[12] = (left + right) * lr; + out[13] = (top + bottom) * bt; + out[14] = (far + near) * nf; + out[15] = 1; + return out; + }; + var isMobile = function isMobile() { + var check = false; + (function (a) { + if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) check = true; + })(navigator.userAgent || navigator.vendor || window.opera); + return check; + }; + var extend = function extend(dest, src) { + for (var key in src) { + if (src.hasOwnProperty(key)) { + dest[key] = src[key]; + } + } + return dest; + }; + var safariCssSizeWorkaround = function safariCssSizeWorkaround(canvas) { + if (isIOS()) { + var width = canvas.style.width; + var height = canvas.style.height; + canvas.style.width = parseInt(width) + 1 + 'px'; + canvas.style.height = parseInt(height) + 'px'; + setTimeout(function () { + canvas.style.width = width; + canvas.style.height = height; + }, 100); + } + window.canvas = canvas; + }; + var frameDataFromPose = function () { + var piOver180 = Math.PI / 180.0; + var rad45 = Math.PI * 0.25; + function mat4_perspectiveFromFieldOfView(out, fov, near, far) { + var upTan = Math.tan(fov ? fov.upDegrees * piOver180 : rad45), + downTan = Math.tan(fov ? fov.downDegrees * piOver180 : rad45), + leftTan = Math.tan(fov ? fov.leftDegrees * piOver180 : rad45), + rightTan = Math.tan(fov ? fov.rightDegrees * piOver180 : rad45), + xScale = 2.0 / (leftTan + rightTan), + yScale = 2.0 / (upTan + downTan); + out[0] = xScale; + out[1] = 0.0; + out[2] = 0.0; + out[3] = 0.0; + out[4] = 0.0; + out[5] = yScale; + out[6] = 0.0; + out[7] = 0.0; + out[8] = -((leftTan - rightTan) * xScale * 0.5); + out[9] = (upTan - downTan) * yScale * 0.5; + out[10] = far / (near - far); + out[11] = -1.0; + out[12] = 0.0; + out[13] = 0.0; + out[14] = far * near / (near - far); + out[15] = 0.0; + return out; + } + function mat4_fromRotationTranslation(out, q, v) { + var x = q[0], + y = q[1], + z = q[2], + w = q[3], + x2 = x + x, + y2 = y + y, + z2 = z + z, + xx = x * x2, + xy = x * y2, + xz = x * z2, + yy = y * y2, + yz = y * z2, + zz = z * z2, + wx = w * x2, + wy = w * y2, + wz = w * z2; + out[0] = 1 - (yy + zz); + out[1] = xy + wz; + out[2] = xz - wy; + out[3] = 0; + out[4] = xy - wz; + out[5] = 1 - (xx + zz); + out[6] = yz + wx; + out[7] = 0; + out[8] = xz + wy; + out[9] = yz - wx; + out[10] = 1 - (xx + yy); + out[11] = 0; + out[12] = v[0]; + out[13] = v[1]; + out[14] = v[2]; + out[15] = 1; + return out; + } + function mat4_translate(out, a, v) { + var x = v[0], + y = v[1], + z = v[2], + a00, + a01, + a02, + a03, + a10, + a11, + a12, + a13, + a20, + a21, + a22, + a23; + if (a === out) { + out[12] = a[0] * x + a[4] * y + a[8] * z + a[12]; + out[13] = a[1] * x + a[5] * y + a[9] * z + a[13]; + out[14] = a[2] * x + a[6] * y + a[10] * z + a[14]; + out[15] = a[3] * x + a[7] * y + a[11] * z + a[15]; + } else { + a00 = a[0]; + a01 = a[1]; + a02 = a[2]; + a03 = a[3]; + a10 = a[4]; + a11 = a[5]; + a12 = a[6]; + a13 = a[7]; + a20 = a[8]; + a21 = a[9]; + a22 = a[10]; + a23 = a[11]; + out[0] = a00; + out[1] = a01; + out[2] = a02; + out[3] = a03; + out[4] = a10; + out[5] = a11; + out[6] = a12; + out[7] = a13; + out[8] = a20; + out[9] = a21; + out[10] = a22; + out[11] = a23; + out[12] = a00 * x + a10 * y + a20 * z + a[12]; + out[13] = a01 * x + a11 * y + a21 * z + a[13]; + out[14] = a02 * x + a12 * y + a22 * z + a[14]; + out[15] = a03 * x + a13 * y + a23 * z + a[15]; + } + return out; + } + function mat4_invert(out, a) { + var a00 = a[0], + a01 = a[1], + a02 = a[2], + a03 = a[3], + a10 = a[4], + a11 = a[5], + a12 = a[6], + a13 = a[7], + a20 = a[8], + a21 = a[9], + a22 = a[10], + a23 = a[11], + a30 = a[12], + a31 = a[13], + a32 = a[14], + a33 = a[15], + b00 = a00 * a11 - a01 * a10, + b01 = a00 * a12 - a02 * a10, + b02 = a00 * a13 - a03 * a10, + b03 = a01 * a12 - a02 * a11, + b04 = a01 * a13 - a03 * a11, + b05 = a02 * a13 - a03 * a12, + b06 = a20 * a31 - a21 * a30, + b07 = a20 * a32 - a22 * a30, + b08 = a20 * a33 - a23 * a30, + b09 = a21 * a32 - a22 * a31, + b10 = a21 * a33 - a23 * a31, + b11 = a22 * a33 - a23 * a32, + det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; + if (!det) { + return null; + } + det = 1.0 / det; + out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; + out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det; + out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det; + out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det; + out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det; + out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det; + out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det; + out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det; + out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det; + out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det; + out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det; + out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det; + out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det; + out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det; + out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det; + out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det; + return out; + } + var defaultOrientation = new Float32Array([0, 0, 0, 1]); + var defaultPosition = new Float32Array([0, 0, 0]); + function updateEyeMatrices(projection, view, pose, fov, offset, vrDisplay) { + mat4_perspectiveFromFieldOfView(projection, fov || null, vrDisplay.depthNear, vrDisplay.depthFar); + var orientation = pose.orientation || defaultOrientation; + var position = pose.position || defaultPosition; + mat4_fromRotationTranslation(view, orientation, position); + if (offset) mat4_translate(view, view, offset); + mat4_invert(view, view); + } + return function (frameData, pose, vrDisplay) { + if (!frameData || !pose) return false; + frameData.pose = pose; + frameData.timestamp = pose.timestamp; + updateEyeMatrices(frameData.leftProjectionMatrix, frameData.leftViewMatrix, pose, vrDisplay._getFieldOfView("left"), vrDisplay._getEyeOffset("left"), vrDisplay); + updateEyeMatrices(frameData.rightProjectionMatrix, frameData.rightViewMatrix, pose, vrDisplay._getFieldOfView("right"), vrDisplay._getEyeOffset("right"), vrDisplay); + return true; + }; + }(); + var isInsideCrossOriginIFrame = function isInsideCrossOriginIFrame() { + var isFramed = window.self !== window.top; + var refOrigin = getOriginFromUrl(document.referrer); + var thisOrigin = getOriginFromUrl(window.location.href); + return isFramed && refOrigin !== thisOrigin; + }; + var getOriginFromUrl = function getOriginFromUrl(url) { + var domainIdx; + var protoSepIdx = url.indexOf("://"); + if (protoSepIdx !== -1) { + domainIdx = protoSepIdx + 3; + } else { + domainIdx = 0; + } + var domainEndIdx = url.indexOf('/', domainIdx); + if (domainEndIdx === -1) { + domainEndIdx = url.length; + } + return url.substring(0, domainEndIdx); + }; + var getQuaternionAngle = function getQuaternionAngle(quat) { + if (quat.w > 1) { + console.warn('getQuaternionAngle: w > 1'); + return 0; + } + var angle = 2 * Math.acos(quat.w); + return angle; + }; + var warnOnce = function () { + var observedWarnings = {}; + return function (key, message) { + if (observedWarnings[key] === undefined) { + console.warn('webvr-polyfill: ' + message); + observedWarnings[key] = true; + } + }; + }(); + var deprecateWarning = function deprecateWarning(deprecated, suggested) { + var alternative = suggested ? 'Please use ' + suggested + ' instead.' : ''; + warnOnce(deprecated, deprecated + ' has been deprecated. ' + 'This may not work on native WebVR displays. ' + alternative); + }; + function WGLUPreserveGLState(gl, bindings, callback) { + if (!bindings) { + callback(gl); + return; + } + var boundValues = []; + var activeTexture = null; + for (var i = 0; i < bindings.length; ++i) { + var binding = bindings[i]; + switch (binding) { + case gl.TEXTURE_BINDING_2D: + case gl.TEXTURE_BINDING_CUBE_MAP: + var textureUnit = bindings[++i]; + if (textureUnit < gl.TEXTURE0 || textureUnit > gl.TEXTURE31) { + console.error("TEXTURE_BINDING_2D or TEXTURE_BINDING_CUBE_MAP must be followed by a valid texture unit"); + boundValues.push(null, null); + break; + } + if (!activeTexture) { + activeTexture = gl.getParameter(gl.ACTIVE_TEXTURE); + } + gl.activeTexture(textureUnit); + boundValues.push(gl.getParameter(binding), null); + break; + case gl.ACTIVE_TEXTURE: + activeTexture = gl.getParameter(gl.ACTIVE_TEXTURE); + boundValues.push(null); + break; + default: + boundValues.push(gl.getParameter(binding)); + break; + } + } + callback(gl); + for (var i = 0; i < bindings.length; ++i) { + var binding = bindings[i]; + var boundValue = boundValues[i]; + switch (binding) { + case gl.ACTIVE_TEXTURE: + break; + case gl.ARRAY_BUFFER_BINDING: + gl.bindBuffer(gl.ARRAY_BUFFER, boundValue); + break; + case gl.COLOR_CLEAR_VALUE: + gl.clearColor(boundValue[0], boundValue[1], boundValue[2], boundValue[3]); + break; + case gl.COLOR_WRITEMASK: + gl.colorMask(boundValue[0], boundValue[1], boundValue[2], boundValue[3]); + break; + case gl.CURRENT_PROGRAM: + gl.useProgram(boundValue); + break; + case gl.ELEMENT_ARRAY_BUFFER_BINDING: + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, boundValue); + break; + case gl.FRAMEBUFFER_BINDING: + gl.bindFramebuffer(gl.FRAMEBUFFER, boundValue); + break; + case gl.RENDERBUFFER_BINDING: + gl.bindRenderbuffer(gl.RENDERBUFFER, boundValue); + break; + case gl.TEXTURE_BINDING_2D: + var textureUnit = bindings[++i]; + if (textureUnit < gl.TEXTURE0 || textureUnit > gl.TEXTURE31) break; + gl.activeTexture(textureUnit); + gl.bindTexture(gl.TEXTURE_2D, boundValue); + break; + case gl.TEXTURE_BINDING_CUBE_MAP: + var textureUnit = bindings[++i]; + if (textureUnit < gl.TEXTURE0 || textureUnit > gl.TEXTURE31) break; + gl.activeTexture(textureUnit); + gl.bindTexture(gl.TEXTURE_CUBE_MAP, boundValue); + break; + case gl.VIEWPORT: + gl.viewport(boundValue[0], boundValue[1], boundValue[2], boundValue[3]); + break; + case gl.BLEND: + case gl.CULL_FACE: + case gl.DEPTH_TEST: + case gl.SCISSOR_TEST: + case gl.STENCIL_TEST: + if (boundValue) { + gl.enable(binding); + } else { + gl.disable(binding); + } + break; + default: + console.log("No GL restore behavior for 0x" + binding.toString(16)); + break; + } + if (activeTexture) { + gl.activeTexture(activeTexture); + } + } + } + var glPreserveState = WGLUPreserveGLState; + var distortionVS = ['attribute vec2 position;', 'attribute vec3 texCoord;', 'varying vec2 vTexCoord;', 'uniform vec4 viewportOffsetScale[2];', 'void main() {', ' vec4 viewport = viewportOffsetScale[int(texCoord.z)];', ' vTexCoord = (texCoord.xy * viewport.zw) + viewport.xy;', ' gl_Position = vec4( position, 1.0, 1.0 );', '}'].join('\n'); + var distortionFS = ['precision mediump float;', 'uniform sampler2D diffuse;', 'varying vec2 vTexCoord;', 'void main() {', ' gl_FragColor = texture2D(diffuse, vTexCoord);', '}'].join('\n'); + function CardboardDistorter(gl, cardboardUI, bufferScale, dirtySubmitFrameBindings) { + this.gl = gl; + this.cardboardUI = cardboardUI; + this.bufferScale = bufferScale; + this.dirtySubmitFrameBindings = dirtySubmitFrameBindings; + this.ctxAttribs = gl.getContextAttributes(); + this.instanceExt = gl.getExtension('ANGLE_instanced_arrays'); + this.meshWidth = 20; + this.meshHeight = 20; + this.bufferWidth = gl.drawingBufferWidth; + this.bufferHeight = gl.drawingBufferHeight; + this.realBindFramebuffer = gl.bindFramebuffer; + this.realEnable = gl.enable; + this.realDisable = gl.disable; + this.realColorMask = gl.colorMask; + this.realClearColor = gl.clearColor; + this.realViewport = gl.viewport; + if (!isIOS()) { + this.realCanvasWidth = Object.getOwnPropertyDescriptor(gl.canvas.__proto__, 'width'); + this.realCanvasHeight = Object.getOwnPropertyDescriptor(gl.canvas.__proto__, 'height'); + } + this.isPatched = false; + this.lastBoundFramebuffer = null; + this.cullFace = false; + this.depthTest = false; + this.blend = false; + this.scissorTest = false; + this.stencilTest = false; + this.viewport = [0, 0, 0, 0]; + this.colorMask = [true, true, true, true]; + this.clearColor = [0, 0, 0, 0]; + this.attribs = { + position: 0, + texCoord: 1 + }; + this.program = linkProgram(gl, distortionVS, distortionFS, this.attribs); + this.uniforms = getProgramUniforms(gl, this.program); + this.viewportOffsetScale = new Float32Array(8); + this.setTextureBounds(); + this.vertexBuffer = gl.createBuffer(); + this.indexBuffer = gl.createBuffer(); + this.indexCount = 0; + this.renderTarget = gl.createTexture(); + this.framebuffer = gl.createFramebuffer(); + this.depthStencilBuffer = null; + this.depthBuffer = null; + this.stencilBuffer = null; + if (this.ctxAttribs.depth && this.ctxAttribs.stencil) { + this.depthStencilBuffer = gl.createRenderbuffer(); + } else if (this.ctxAttribs.depth) { + this.depthBuffer = gl.createRenderbuffer(); + } else if (this.ctxAttribs.stencil) { + this.stencilBuffer = gl.createRenderbuffer(); + } + this.patch(); + this.onResize(); + } + CardboardDistorter.prototype.destroy = function () { + var gl = this.gl; + this.unpatch(); + gl.deleteProgram(this.program); + gl.deleteBuffer(this.vertexBuffer); + gl.deleteBuffer(this.indexBuffer); + gl.deleteTexture(this.renderTarget); + gl.deleteFramebuffer(this.framebuffer); + if (this.depthStencilBuffer) { + gl.deleteRenderbuffer(this.depthStencilBuffer); + } + if (this.depthBuffer) { + gl.deleteRenderbuffer(this.depthBuffer); + } + if (this.stencilBuffer) { + gl.deleteRenderbuffer(this.stencilBuffer); + } + if (this.cardboardUI) { + this.cardboardUI.destroy(); + } + }; + CardboardDistorter.prototype.onResize = function () { + var gl = this.gl; + var self = this; + var glState = [gl.RENDERBUFFER_BINDING, gl.TEXTURE_BINDING_2D, gl.TEXTURE0]; + glPreserveState(gl, glState, function (gl) { + self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, null); + if (self.scissorTest) { + self.realDisable.call(gl, gl.SCISSOR_TEST); + } + self.realColorMask.call(gl, true, true, true, true); + self.realViewport.call(gl, 0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); + self.realClearColor.call(gl, 0, 0, 0, 1); + gl.clear(gl.COLOR_BUFFER_BIT); + self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, self.framebuffer); + gl.bindTexture(gl.TEXTURE_2D, self.renderTarget); + gl.texImage2D(gl.TEXTURE_2D, 0, self.ctxAttribs.alpha ? gl.RGBA : gl.RGB, self.bufferWidth, self.bufferHeight, 0, self.ctxAttribs.alpha ? gl.RGBA : gl.RGB, gl.UNSIGNED_BYTE, null); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, self.renderTarget, 0); + if (self.ctxAttribs.depth && self.ctxAttribs.stencil) { + gl.bindRenderbuffer(gl.RENDERBUFFER, self.depthStencilBuffer); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, self.bufferWidth, self.bufferHeight); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, self.depthStencilBuffer); + } else if (self.ctxAttribs.depth) { + gl.bindRenderbuffer(gl.RENDERBUFFER, self.depthBuffer); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, self.bufferWidth, self.bufferHeight); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, self.depthBuffer); + } else if (self.ctxAttribs.stencil) { + gl.bindRenderbuffer(gl.RENDERBUFFER, self.stencilBuffer); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, self.bufferWidth, self.bufferHeight); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, self.stencilBuffer); + } + if (!gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE) { + console.error('Framebuffer incomplete!'); + } + self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, self.lastBoundFramebuffer); + if (self.scissorTest) { + self.realEnable.call(gl, gl.SCISSOR_TEST); + } + self.realColorMask.apply(gl, self.colorMask); + self.realViewport.apply(gl, self.viewport); + self.realClearColor.apply(gl, self.clearColor); + }); + if (this.cardboardUI) { + this.cardboardUI.onResize(); + } + }; + CardboardDistorter.prototype.patch = function () { + if (this.isPatched) { + return; + } + var self = this; + var canvas = this.gl.canvas; + var gl = this.gl; + if (!isIOS()) { + canvas.width = getScreenWidth() * this.bufferScale; + canvas.height = getScreenHeight() * this.bufferScale; + Object.defineProperty(canvas, 'width', { + configurable: true, + enumerable: true, + get: function get() { + return self.bufferWidth; + }, + set: function set(value) { + self.bufferWidth = value; + self.realCanvasWidth.set.call(canvas, value); + self.onResize(); + } + }); + Object.defineProperty(canvas, 'height', { + configurable: true, + enumerable: true, + get: function get() { + return self.bufferHeight; + }, + set: function set(value) { + self.bufferHeight = value; + self.realCanvasHeight.set.call(canvas, value); + self.onResize(); + } + }); + } + this.lastBoundFramebuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING); + if (this.lastBoundFramebuffer == null) { + this.lastBoundFramebuffer = this.framebuffer; + this.gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer); + } + this.gl.bindFramebuffer = function (target, framebuffer) { + self.lastBoundFramebuffer = framebuffer ? framebuffer : self.framebuffer; + self.realBindFramebuffer.call(gl, target, self.lastBoundFramebuffer); + }; + this.cullFace = gl.getParameter(gl.CULL_FACE); + this.depthTest = gl.getParameter(gl.DEPTH_TEST); + this.blend = gl.getParameter(gl.BLEND); + this.scissorTest = gl.getParameter(gl.SCISSOR_TEST); + this.stencilTest = gl.getParameter(gl.STENCIL_TEST); + gl.enable = function (pname) { + switch (pname) { + case gl.CULL_FACE: + self.cullFace = true; + break; + case gl.DEPTH_TEST: + self.depthTest = true; + break; + case gl.BLEND: + self.blend = true; + break; + case gl.SCISSOR_TEST: + self.scissorTest = true; + break; + case gl.STENCIL_TEST: + self.stencilTest = true; + break; + } + self.realEnable.call(gl, pname); + }; + gl.disable = function (pname) { + switch (pname) { + case gl.CULL_FACE: + self.cullFace = false; + break; + case gl.DEPTH_TEST: + self.depthTest = false; + break; + case gl.BLEND: + self.blend = false; + break; + case gl.SCISSOR_TEST: + self.scissorTest = false; + break; + case gl.STENCIL_TEST: + self.stencilTest = false; + break; + } + self.realDisable.call(gl, pname); + }; + this.colorMask = gl.getParameter(gl.COLOR_WRITEMASK); + gl.colorMask = function (r, g, b, a) { + self.colorMask[0] = r; + self.colorMask[1] = g; + self.colorMask[2] = b; + self.colorMask[3] = a; + self.realColorMask.call(gl, r, g, b, a); + }; + this.clearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE); + gl.clearColor = function (r, g, b, a) { + self.clearColor[0] = r; + self.clearColor[1] = g; + self.clearColor[2] = b; + self.clearColor[3] = a; + self.realClearColor.call(gl, r, g, b, a); + }; + this.viewport = gl.getParameter(gl.VIEWPORT); + gl.viewport = function (x, y, w, h) { + self.viewport[0] = x; + self.viewport[1] = y; + self.viewport[2] = w; + self.viewport[3] = h; + self.realViewport.call(gl, x, y, w, h); + }; + this.isPatched = true; + safariCssSizeWorkaround(canvas); + }; + CardboardDistorter.prototype.unpatch = function () { + if (!this.isPatched) { + return; + } + var gl = this.gl; + var canvas = this.gl.canvas; + if (!isIOS()) { + Object.defineProperty(canvas, 'width', this.realCanvasWidth); + Object.defineProperty(canvas, 'height', this.realCanvasHeight); + } + canvas.width = this.bufferWidth; + canvas.height = this.bufferHeight; + gl.bindFramebuffer = this.realBindFramebuffer; + gl.enable = this.realEnable; + gl.disable = this.realDisable; + gl.colorMask = this.realColorMask; + gl.clearColor = this.realClearColor; + gl.viewport = this.realViewport; + if (this.lastBoundFramebuffer == this.framebuffer) { + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + } + this.isPatched = false; + setTimeout(function () { + safariCssSizeWorkaround(canvas); + }, 1); + }; + CardboardDistorter.prototype.setTextureBounds = function (leftBounds, rightBounds) { + if (!leftBounds) { + leftBounds = [0, 0, 0.5, 1]; + } + if (!rightBounds) { + rightBounds = [0.5, 0, 0.5, 1]; + } + this.viewportOffsetScale[0] = leftBounds[0]; + this.viewportOffsetScale[1] = leftBounds[1]; + this.viewportOffsetScale[2] = leftBounds[2]; + this.viewportOffsetScale[3] = leftBounds[3]; + this.viewportOffsetScale[4] = rightBounds[0]; + this.viewportOffsetScale[5] = rightBounds[1]; + this.viewportOffsetScale[6] = rightBounds[2]; + this.viewportOffsetScale[7] = rightBounds[3]; + }; + CardboardDistorter.prototype.submitFrame = function () { + var gl = this.gl; + var self = this; + var glState = []; + if (!this.dirtySubmitFrameBindings) { + glState.push(gl.CURRENT_PROGRAM, gl.ARRAY_BUFFER_BINDING, gl.ELEMENT_ARRAY_BUFFER_BINDING, gl.TEXTURE_BINDING_2D, gl.TEXTURE0); + } + glPreserveState(gl, glState, function (gl) { + self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, null); + var positionDivisor = 0; + var texCoordDivisor = 0; + if (self.instanceExt) { + positionDivisor = gl.getVertexAttrib(self.attribs.position, self.instanceExt.VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE); + texCoordDivisor = gl.getVertexAttrib(self.attribs.texCoord, self.instanceExt.VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE); + } + if (self.cullFace) { + self.realDisable.call(gl, gl.CULL_FACE); + } + if (self.depthTest) { + self.realDisable.call(gl, gl.DEPTH_TEST); + } + if (self.blend) { + self.realDisable.call(gl, gl.BLEND); + } + if (self.scissorTest) { + self.realDisable.call(gl, gl.SCISSOR_TEST); + } + if (self.stencilTest) { + self.realDisable.call(gl, gl.STENCIL_TEST); + } + self.realColorMask.call(gl, true, true, true, true); + self.realViewport.call(gl, 0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); + if (self.ctxAttribs.alpha || isIOS()) { + self.realClearColor.call(gl, 0, 0, 0, 1); + gl.clear(gl.COLOR_BUFFER_BIT); + } + gl.useProgram(self.program); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.indexBuffer); + gl.bindBuffer(gl.ARRAY_BUFFER, self.vertexBuffer); + gl.enableVertexAttribArray(self.attribs.position); + gl.enableVertexAttribArray(self.attribs.texCoord); + gl.vertexAttribPointer(self.attribs.position, 2, gl.FLOAT, false, 20, 0); + gl.vertexAttribPointer(self.attribs.texCoord, 3, gl.FLOAT, false, 20, 8); + if (self.instanceExt) { + if (positionDivisor != 0) { + self.instanceExt.vertexAttribDivisorANGLE(self.attribs.position, 0); + } + if (texCoordDivisor != 0) { + self.instanceExt.vertexAttribDivisorANGLE(self.attribs.texCoord, 0); + } + } + gl.activeTexture(gl.TEXTURE0); + gl.uniform1i(self.uniforms.diffuse, 0); + gl.bindTexture(gl.TEXTURE_2D, self.renderTarget); + gl.uniform4fv(self.uniforms.viewportOffsetScale, self.viewportOffsetScale); + gl.drawElements(gl.TRIANGLES, self.indexCount, gl.UNSIGNED_SHORT, 0); + if (self.cardboardUI) { + self.cardboardUI.renderNoState(); + } + self.realBindFramebuffer.call(self.gl, gl.FRAMEBUFFER, self.framebuffer); + if (!self.ctxAttribs.preserveDrawingBuffer) { + self.realClearColor.call(gl, 0, 0, 0, 0); + gl.clear(gl.COLOR_BUFFER_BIT); + } + if (!self.dirtySubmitFrameBindings) { + self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, self.lastBoundFramebuffer); + } + if (self.cullFace) { + self.realEnable.call(gl, gl.CULL_FACE); + } + if (self.depthTest) { + self.realEnable.call(gl, gl.DEPTH_TEST); + } + if (self.blend) { + self.realEnable.call(gl, gl.BLEND); + } + if (self.scissorTest) { + self.realEnable.call(gl, gl.SCISSOR_TEST); + } + if (self.stencilTest) { + self.realEnable.call(gl, gl.STENCIL_TEST); + } + self.realColorMask.apply(gl, self.colorMask); + self.realViewport.apply(gl, self.viewport); + if (self.ctxAttribs.alpha || !self.ctxAttribs.preserveDrawingBuffer) { + self.realClearColor.apply(gl, self.clearColor); + } + if (self.instanceExt) { + if (positionDivisor != 0) { + self.instanceExt.vertexAttribDivisorANGLE(self.attribs.position, positionDivisor); + } + if (texCoordDivisor != 0) { + self.instanceExt.vertexAttribDivisorANGLE(self.attribs.texCoord, texCoordDivisor); + } + } + }); + if (isIOS()) { + var canvas = gl.canvas; + if (canvas.width != self.bufferWidth || canvas.height != self.bufferHeight) { + self.bufferWidth = canvas.width; + self.bufferHeight = canvas.height; + self.onResize(); + } + } + }; + CardboardDistorter.prototype.updateDeviceInfo = function (deviceInfo) { + var gl = this.gl; + var self = this; + var glState = [gl.ARRAY_BUFFER_BINDING, gl.ELEMENT_ARRAY_BUFFER_BINDING]; + glPreserveState(gl, glState, function (gl) { + var vertices = self.computeMeshVertices_(self.meshWidth, self.meshHeight, deviceInfo); + gl.bindBuffer(gl.ARRAY_BUFFER, self.vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); + if (!self.indexCount) { + var indices = self.computeMeshIndices_(self.meshWidth, self.meshHeight); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW); + self.indexCount = indices.length; + } + }); + }; + CardboardDistorter.prototype.computeMeshVertices_ = function (width, height, deviceInfo) { + var vertices = new Float32Array(2 * width * height * 5); + var lensFrustum = deviceInfo.getLeftEyeVisibleTanAngles(); + var noLensFrustum = deviceInfo.getLeftEyeNoLensTanAngles(); + var viewport = deviceInfo.getLeftEyeVisibleScreenRect(noLensFrustum); + var vidx = 0; + for (var e = 0; e < 2; e++) { + for (var j = 0; j < height; j++) { + for (var i = 0; i < width; i++, vidx++) { + var u = i / (width - 1); + var v = j / (height - 1); + var s = u; + var t = v; + var x = lerp(lensFrustum[0], lensFrustum[2], u); + var y = lerp(lensFrustum[3], lensFrustum[1], v); + var d = Math.sqrt(x * x + y * y); + var r = deviceInfo.distortion.distortInverse(d); + var p = x * r / d; + var q = y * r / d; + u = (p - noLensFrustum[0]) / (noLensFrustum[2] - noLensFrustum[0]); + v = (q - noLensFrustum[3]) / (noLensFrustum[1] - noLensFrustum[3]); + u = (viewport.x + u * viewport.width - 0.5) * 2.0; + v = (viewport.y + v * viewport.height - 0.5) * 2.0; + vertices[vidx * 5 + 0] = u; + vertices[vidx * 5 + 1] = v; + vertices[vidx * 5 + 2] = s; + vertices[vidx * 5 + 3] = t; + vertices[vidx * 5 + 4] = e; + } + } + var w = lensFrustum[2] - lensFrustum[0]; + lensFrustum[0] = -(w + lensFrustum[0]); + lensFrustum[2] = w - lensFrustum[2]; + w = noLensFrustum[2] - noLensFrustum[0]; + noLensFrustum[0] = -(w + noLensFrustum[0]); + noLensFrustum[2] = w - noLensFrustum[2]; + viewport.x = 1 - (viewport.x + viewport.width); + } + return vertices; + }; + CardboardDistorter.prototype.computeMeshIndices_ = function (width, height) { + var indices = new Uint16Array(2 * (width - 1) * (height - 1) * 6); + var halfwidth = width / 2; + var halfheight = height / 2; + var vidx = 0; + var iidx = 0; + for (var e = 0; e < 2; e++) { + for (var j = 0; j < height; j++) { + for (var i = 0; i < width; i++, vidx++) { + if (i == 0 || j == 0) continue; + if (i <= halfwidth == j <= halfheight) { + indices[iidx++] = vidx; + indices[iidx++] = vidx - width - 1; + indices[iidx++] = vidx - width; + indices[iidx++] = vidx - width - 1; + indices[iidx++] = vidx; + indices[iidx++] = vidx - 1; + } else { + indices[iidx++] = vidx - 1; + indices[iidx++] = vidx - width; + indices[iidx++] = vidx; + indices[iidx++] = vidx - width; + indices[iidx++] = vidx - 1; + indices[iidx++] = vidx - width - 1; + } + } + } + } + return indices; + }; + CardboardDistorter.prototype.getOwnPropertyDescriptor_ = function (proto, attrName) { + var descriptor = Object.getOwnPropertyDescriptor(proto, attrName); + if (descriptor.get === undefined || descriptor.set === undefined) { + descriptor.configurable = true; + descriptor.enumerable = true; + descriptor.get = function () { + return this.getAttribute(attrName); + }; + descriptor.set = function (val) { + this.setAttribute(attrName, val); + }; + } + return descriptor; + }; + var uiVS = ['attribute vec2 position;', 'uniform mat4 projectionMat;', 'void main() {', ' gl_Position = projectionMat * vec4( position, -1.0, 1.0 );', '}'].join('\n'); + var uiFS = ['precision mediump float;', 'uniform vec4 color;', 'void main() {', ' gl_FragColor = color;', '}'].join('\n'); + var DEG2RAD = Math.PI / 180.0; + var kAnglePerGearSection = 60; + var kOuterRimEndAngle = 12; + var kInnerRimBeginAngle = 20; + var kOuterRadius = 1; + var kMiddleRadius = 0.75; + var kInnerRadius = 0.3125; + var kCenterLineThicknessDp = 4; + var kButtonWidthDp = 28; + var kTouchSlopFactor = 1.5; + function CardboardUI(gl) { + this.gl = gl; + this.attribs = { + position: 0 + }; + this.program = linkProgram(gl, uiVS, uiFS, this.attribs); + this.uniforms = getProgramUniforms(gl, this.program); + this.vertexBuffer = gl.createBuffer(); + this.gearOffset = 0; + this.gearVertexCount = 0; + this.arrowOffset = 0; + this.arrowVertexCount = 0; + this.projMat = new Float32Array(16); + this.listener = null; + this.onResize(); + } + CardboardUI.prototype.destroy = function () { + var gl = this.gl; + if (this.listener) { + gl.canvas.removeEventListener('click', this.listener, false); + } + gl.deleteProgram(this.program); + gl.deleteBuffer(this.vertexBuffer); + }; + CardboardUI.prototype.listen = function (optionsCallback, backCallback) { + var canvas = this.gl.canvas; + this.listener = function (event) { + var midline = canvas.clientWidth / 2; + var buttonSize = kButtonWidthDp * kTouchSlopFactor; + if (event.clientX > midline - buttonSize && event.clientX < midline + buttonSize && event.clientY > canvas.clientHeight - buttonSize) { + optionsCallback(event); + } else if (event.clientX < buttonSize && event.clientY < buttonSize) { + backCallback(event); + } + }; + canvas.addEventListener('click', this.listener, false); + }; + CardboardUI.prototype.onResize = function () { + var gl = this.gl; + var self = this; + var glState = [gl.ARRAY_BUFFER_BINDING]; + glPreserveState(gl, glState, function (gl) { + var vertices = []; + var midline = gl.drawingBufferWidth / 2; + var physicalPixels = Math.max(screen.width, screen.height) * window.devicePixelRatio; + var scalingRatio = gl.drawingBufferWidth / physicalPixels; + var dps = scalingRatio * window.devicePixelRatio; + var lineWidth = kCenterLineThicknessDp * dps / 2; + var buttonSize = kButtonWidthDp * kTouchSlopFactor * dps; + var buttonScale = kButtonWidthDp * dps / 2; + var buttonBorder = (kButtonWidthDp * kTouchSlopFactor - kButtonWidthDp) * dps; + vertices.push(midline - lineWidth, buttonSize); + vertices.push(midline - lineWidth, gl.drawingBufferHeight); + vertices.push(midline + lineWidth, buttonSize); + vertices.push(midline + lineWidth, gl.drawingBufferHeight); + self.gearOffset = vertices.length / 2; + function addGearSegment(theta, r) { + var angle = (90 - theta) * DEG2RAD; + var x = Math.cos(angle); + var y = Math.sin(angle); + vertices.push(kInnerRadius * x * buttonScale + midline, kInnerRadius * y * buttonScale + buttonScale); + vertices.push(r * x * buttonScale + midline, r * y * buttonScale + buttonScale); + } + for (var i = 0; i <= 6; i++) { + var segmentTheta = i * kAnglePerGearSection; + addGearSegment(segmentTheta, kOuterRadius); + addGearSegment(segmentTheta + kOuterRimEndAngle, kOuterRadius); + addGearSegment(segmentTheta + kInnerRimBeginAngle, kMiddleRadius); + addGearSegment(segmentTheta + (kAnglePerGearSection - kInnerRimBeginAngle), kMiddleRadius); + addGearSegment(segmentTheta + (kAnglePerGearSection - kOuterRimEndAngle), kOuterRadius); + } + self.gearVertexCount = vertices.length / 2 - self.gearOffset; + self.arrowOffset = vertices.length / 2; + function addArrowVertex(x, y) { + vertices.push(buttonBorder + x, gl.drawingBufferHeight - buttonBorder - y); + } + var angledLineWidth = lineWidth / Math.sin(45 * DEG2RAD); + addArrowVertex(0, buttonScale); + addArrowVertex(buttonScale, 0); + addArrowVertex(buttonScale + angledLineWidth, angledLineWidth); + addArrowVertex(angledLineWidth, buttonScale + angledLineWidth); + addArrowVertex(angledLineWidth, buttonScale - angledLineWidth); + addArrowVertex(0, buttonScale); + addArrowVertex(buttonScale, buttonScale * 2); + addArrowVertex(buttonScale + angledLineWidth, buttonScale * 2 - angledLineWidth); + addArrowVertex(angledLineWidth, buttonScale - angledLineWidth); + addArrowVertex(0, buttonScale); + addArrowVertex(angledLineWidth, buttonScale - lineWidth); + addArrowVertex(kButtonWidthDp * dps, buttonScale - lineWidth); + addArrowVertex(angledLineWidth, buttonScale + lineWidth); + addArrowVertex(kButtonWidthDp * dps, buttonScale + lineWidth); + self.arrowVertexCount = vertices.length / 2 - self.arrowOffset; + gl.bindBuffer(gl.ARRAY_BUFFER, self.vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); + }); + }; + CardboardUI.prototype.render = function () { + var gl = this.gl; + var self = this; + var glState = [gl.CULL_FACE, gl.DEPTH_TEST, gl.BLEND, gl.SCISSOR_TEST, gl.STENCIL_TEST, gl.COLOR_WRITEMASK, gl.VIEWPORT, gl.CURRENT_PROGRAM, gl.ARRAY_BUFFER_BINDING]; + glPreserveState(gl, glState, function (gl) { + gl.disable(gl.CULL_FACE); + gl.disable(gl.DEPTH_TEST); + gl.disable(gl.BLEND); + gl.disable(gl.SCISSOR_TEST); + gl.disable(gl.STENCIL_TEST); + gl.colorMask(true, true, true, true); + gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); + self.renderNoState(); + }); + }; + CardboardUI.prototype.renderNoState = function () { + var gl = this.gl; + gl.useProgram(this.program); + gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); + gl.enableVertexAttribArray(this.attribs.position); + gl.vertexAttribPointer(this.attribs.position, 2, gl.FLOAT, false, 8, 0); + gl.uniform4f(this.uniforms.color, 1.0, 1.0, 1.0, 1.0); + orthoMatrix(this.projMat, 0, gl.drawingBufferWidth, 0, gl.drawingBufferHeight, 0.1, 1024.0); + gl.uniformMatrix4fv(this.uniforms.projectionMat, false, this.projMat); + gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); + gl.drawArrays(gl.TRIANGLE_STRIP, this.gearOffset, this.gearVertexCount); + gl.drawArrays(gl.TRIANGLE_STRIP, this.arrowOffset, this.arrowVertexCount); + }; + function Distortion(coefficients) { + this.coefficients = coefficients; + } + Distortion.prototype.distortInverse = function (radius) { + var r0 = 0; + var r1 = 1; + var dr0 = radius - this.distort(r0); + while (Math.abs(r1 - r0) > 0.0001) { + var dr1 = radius - this.distort(r1); + var r2 = r1 - dr1 * ((r1 - r0) / (dr1 - dr0)); + r0 = r1; + r1 = r2; + dr0 = dr1; + } + return r1; + }; + Distortion.prototype.distort = function (radius) { + var r2 = radius * radius; + var ret = 0; + for (var i = 0; i < this.coefficients.length; i++) { + ret = r2 * (ret + this.coefficients[i]); + } + return (ret + 1) * radius; + }; + var degToRad = Math.PI / 180; + var radToDeg = 180 / Math.PI; + var Vector3 = function Vector3(x, y, z) { + this.x = x || 0; + this.y = y || 0; + this.z = z || 0; + }; + Vector3.prototype = { + constructor: Vector3, + set: function set(x, y, z) { + this.x = x; + this.y = y; + this.z = z; + return this; + }, + copy: function copy(v) { + this.x = v.x; + this.y = v.y; + this.z = v.z; + return this; + }, + length: function length() { + return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); + }, + normalize: function normalize() { + var scalar = this.length(); + if (scalar !== 0) { + var invScalar = 1 / scalar; + this.multiplyScalar(invScalar); + } else { + this.x = 0; + this.y = 0; + this.z = 0; + } + return this; + }, + multiplyScalar: function multiplyScalar(scalar) { + this.x *= scalar; + this.y *= scalar; + this.z *= scalar; + }, + applyQuaternion: function applyQuaternion(q) { + var x = this.x; + var y = this.y; + var z = this.z; + var qx = q.x; + var qy = q.y; + var qz = q.z; + var qw = q.w; + var ix = qw * x + qy * z - qz * y; + var iy = qw * y + qz * x - qx * z; + var iz = qw * z + qx * y - qy * x; + var iw = -qx * x - qy * y - qz * z; + this.x = ix * qw + iw * -qx + iy * -qz - iz * -qy; + this.y = iy * qw + iw * -qy + iz * -qx - ix * -qz; + this.z = iz * qw + iw * -qz + ix * -qy - iy * -qx; + return this; + }, + dot: function dot(v) { + return this.x * v.x + this.y * v.y + this.z * v.z; + }, + crossVectors: function crossVectors(a, b) { + var ax = a.x, + ay = a.y, + az = a.z; + var bx = b.x, + by = b.y, + bz = b.z; + this.x = ay * bz - az * by; + this.y = az * bx - ax * bz; + this.z = ax * by - ay * bx; + return this; + } + }; + var Quaternion = function Quaternion(x, y, z, w) { + this.x = x || 0; + this.y = y || 0; + this.z = z || 0; + this.w = w !== undefined ? w : 1; + }; + Quaternion.prototype = { + constructor: Quaternion, + set: function set(x, y, z, w) { + this.x = x; + this.y = y; + this.z = z; + this.w = w; + return this; + }, + copy: function copy(quaternion) { + this.x = quaternion.x; + this.y = quaternion.y; + this.z = quaternion.z; + this.w = quaternion.w; + return this; + }, + setFromEulerXYZ: function setFromEulerXYZ(x, y, z) { + var c1 = Math.cos(x / 2); + var c2 = Math.cos(y / 2); + var c3 = Math.cos(z / 2); + var s1 = Math.sin(x / 2); + var s2 = Math.sin(y / 2); + var s3 = Math.sin(z / 2); + this.x = s1 * c2 * c3 + c1 * s2 * s3; + this.y = c1 * s2 * c3 - s1 * c2 * s3; + this.z = c1 * c2 * s3 + s1 * s2 * c3; + this.w = c1 * c2 * c3 - s1 * s2 * s3; + return this; + }, + setFromEulerYXZ: function setFromEulerYXZ(x, y, z) { + var c1 = Math.cos(x / 2); + var c2 = Math.cos(y / 2); + var c3 = Math.cos(z / 2); + var s1 = Math.sin(x / 2); + var s2 = Math.sin(y / 2); + var s3 = Math.sin(z / 2); + this.x = s1 * c2 * c3 + c1 * s2 * s3; + this.y = c1 * s2 * c3 - s1 * c2 * s3; + this.z = c1 * c2 * s3 - s1 * s2 * c3; + this.w = c1 * c2 * c3 + s1 * s2 * s3; + return this; + }, + setFromAxisAngle: function setFromAxisAngle(axis, angle) { + var halfAngle = angle / 2, + s = Math.sin(halfAngle); + this.x = axis.x * s; + this.y = axis.y * s; + this.z = axis.z * s; + this.w = Math.cos(halfAngle); + return this; + }, + multiply: function multiply(q) { + return this.multiplyQuaternions(this, q); + }, + multiplyQuaternions: function multiplyQuaternions(a, b) { + var qax = a.x, + qay = a.y, + qaz = a.z, + qaw = a.w; + var qbx = b.x, + qby = b.y, + qbz = b.z, + qbw = b.w; + this.x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; + this.y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; + this.z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; + this.w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; + return this; + }, + inverse: function inverse() { + this.x *= -1; + this.y *= -1; + this.z *= -1; + this.normalize(); + return this; + }, + normalize: function normalize() { + var l = Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w); + if (l === 0) { + this.x = 0; + this.y = 0; + this.z = 0; + this.w = 1; + } else { + l = 1 / l; + this.x = this.x * l; + this.y = this.y * l; + this.z = this.z * l; + this.w = this.w * l; + } + return this; + }, + slerp: function slerp(qb, t) { + if (t === 0) return this; + if (t === 1) return this.copy(qb); + var x = this.x, + y = this.y, + z = this.z, + w = this.w; + var cosHalfTheta = w * qb.w + x * qb.x + y * qb.y + z * qb.z; + if (cosHalfTheta < 0) { + this.w = -qb.w; + this.x = -qb.x; + this.y = -qb.y; + this.z = -qb.z; + cosHalfTheta = -cosHalfTheta; + } else { + this.copy(qb); + } + if (cosHalfTheta >= 1.0) { + this.w = w; + this.x = x; + this.y = y; + this.z = z; + return this; + } + var halfTheta = Math.acos(cosHalfTheta); + var sinHalfTheta = Math.sqrt(1.0 - cosHalfTheta * cosHalfTheta); + if (Math.abs(sinHalfTheta) < 0.001) { + this.w = 0.5 * (w + this.w); + this.x = 0.5 * (x + this.x); + this.y = 0.5 * (y + this.y); + this.z = 0.5 * (z + this.z); + return this; + } + var ratioA = Math.sin((1 - t) * halfTheta) / sinHalfTheta, + ratioB = Math.sin(t * halfTheta) / sinHalfTheta; + this.w = w * ratioA + this.w * ratioB; + this.x = x * ratioA + this.x * ratioB; + this.y = y * ratioA + this.y * ratioB; + this.z = z * ratioA + this.z * ratioB; + return this; + }, + setFromUnitVectors: function () { + var v1, r; + var EPS = 0.000001; + return function (vFrom, vTo) { + if (v1 === undefined) v1 = new Vector3(); + r = vFrom.dot(vTo) + 1; + if (r < EPS) { + r = 0; + if (Math.abs(vFrom.x) > Math.abs(vFrom.z)) { + v1.set(-vFrom.y, vFrom.x, 0); + } else { + v1.set(0, -vFrom.z, vFrom.y); + } + } else { + v1.crossVectors(vFrom, vTo); + } + this.x = v1.x; + this.y = v1.y; + this.z = v1.z; + this.w = r; + this.normalize(); + return this; + }; + }() + }; + function Device(params) { + this.width = params.width || getScreenWidth(); + this.height = params.height || getScreenHeight(); + this.widthMeters = params.widthMeters; + this.heightMeters = params.heightMeters; + this.bevelMeters = params.bevelMeters; + } + var DEFAULT_ANDROID = new Device({ + widthMeters: 0.110, + heightMeters: 0.062, + bevelMeters: 0.004 + }); + var DEFAULT_IOS = new Device({ + widthMeters: 0.1038, + heightMeters: 0.0584, + bevelMeters: 0.004 + }); + var Viewers = { + CardboardV1: new CardboardViewer({ + id: 'CardboardV1', + label: 'Cardboard I/O 2014', + fov: 40, + interLensDistance: 0.060, + baselineLensDistance: 0.035, + screenLensDistance: 0.042, + distortionCoefficients: [0.441, 0.156], + inverseCoefficients: [-0.4410035, 0.42756155, -0.4804439, 0.5460139, -0.58821183, 0.5733938, -0.48303202, 0.33299083, -0.17573841, 0.0651772, -0.01488963, 0.001559834] + }), + CardboardV2: new CardboardViewer({ + id: 'CardboardV2', + label: 'Cardboard I/O 2015', + fov: 60, + interLensDistance: 0.064, + baselineLensDistance: 0.035, + screenLensDistance: 0.039, + distortionCoefficients: [0.34, 0.55], + inverseCoefficients: [-0.33836704, -0.18162185, 0.862655, -1.2462051, 1.0560602, -0.58208317, 0.21609078, -0.05444823, 0.009177956, -9.904169E-4, 6.183535E-5, -1.6981803E-6] + }) + }; + function DeviceInfo(deviceParams, additionalViewers) { + this.viewer = Viewers.CardboardV2; + this.updateDeviceParams(deviceParams); + this.distortion = new Distortion(this.viewer.distortionCoefficients); + for (var i = 0; i < additionalViewers.length; i++) { + var viewer = additionalViewers[i]; + Viewers[viewer.id] = new CardboardViewer(viewer); + } + } + DeviceInfo.prototype.updateDeviceParams = function (deviceParams) { + this.device = this.determineDevice_(deviceParams) || this.device; + }; + DeviceInfo.prototype.getDevice = function () { + return this.device; + }; + DeviceInfo.prototype.setViewer = function (viewer) { + this.viewer = viewer; + this.distortion = new Distortion(this.viewer.distortionCoefficients); + }; + DeviceInfo.prototype.determineDevice_ = function (deviceParams) { + if (!deviceParams) { + if (isIOS()) { + console.warn('Using fallback iOS device measurements.'); + return DEFAULT_IOS; + } else { + console.warn('Using fallback Android device measurements.'); + return DEFAULT_ANDROID; + } + } + var METERS_PER_INCH = 0.0254; + var metersPerPixelX = METERS_PER_INCH / deviceParams.xdpi; + var metersPerPixelY = METERS_PER_INCH / deviceParams.ydpi; + var width = getScreenWidth(); + var height = getScreenHeight(); + return new Device({ + widthMeters: metersPerPixelX * width, + heightMeters: metersPerPixelY * height, + bevelMeters: deviceParams.bevelMm * 0.001 + }); + }; + DeviceInfo.prototype.getDistortedFieldOfViewLeftEye = function () { + var viewer = this.viewer; + var device = this.device; + var distortion = this.distortion; + var eyeToScreenDistance = viewer.screenLensDistance; + var outerDist = (device.widthMeters - viewer.interLensDistance) / 2; + var innerDist = viewer.interLensDistance / 2; + var bottomDist = viewer.baselineLensDistance - device.bevelMeters; + var topDist = device.heightMeters - bottomDist; + var outerAngle = radToDeg * Math.atan(distortion.distort(outerDist / eyeToScreenDistance)); + var innerAngle = radToDeg * Math.atan(distortion.distort(innerDist / eyeToScreenDistance)); + var bottomAngle = radToDeg * Math.atan(distortion.distort(bottomDist / eyeToScreenDistance)); + var topAngle = radToDeg * Math.atan(distortion.distort(topDist / eyeToScreenDistance)); + return { + leftDegrees: Math.min(outerAngle, viewer.fov), + rightDegrees: Math.min(innerAngle, viewer.fov), + downDegrees: Math.min(bottomAngle, viewer.fov), + upDegrees: Math.min(topAngle, viewer.fov) + }; + }; + DeviceInfo.prototype.getLeftEyeVisibleTanAngles = function () { + var viewer = this.viewer; + var device = this.device; + var distortion = this.distortion; + var fovLeft = Math.tan(-degToRad * viewer.fov); + var fovTop = Math.tan(degToRad * viewer.fov); + var fovRight = Math.tan(degToRad * viewer.fov); + var fovBottom = Math.tan(-degToRad * viewer.fov); + var halfWidth = device.widthMeters / 4; + var halfHeight = device.heightMeters / 2; + var verticalLensOffset = viewer.baselineLensDistance - device.bevelMeters - halfHeight; + var centerX = viewer.interLensDistance / 2 - halfWidth; + var centerY = -verticalLensOffset; + var centerZ = viewer.screenLensDistance; + var screenLeft = distortion.distort((centerX - halfWidth) / centerZ); + var screenTop = distortion.distort((centerY + halfHeight) / centerZ); + var screenRight = distortion.distort((centerX + halfWidth) / centerZ); + var screenBottom = distortion.distort((centerY - halfHeight) / centerZ); + var result = new Float32Array(4); + result[0] = Math.max(fovLeft, screenLeft); + result[1] = Math.min(fovTop, screenTop); + result[2] = Math.min(fovRight, screenRight); + result[3] = Math.max(fovBottom, screenBottom); + return result; + }; + DeviceInfo.prototype.getLeftEyeNoLensTanAngles = function () { + var viewer = this.viewer; + var device = this.device; + var distortion = this.distortion; + var result = new Float32Array(4); + var fovLeft = distortion.distortInverse(Math.tan(-degToRad * viewer.fov)); + var fovTop = distortion.distortInverse(Math.tan(degToRad * viewer.fov)); + var fovRight = distortion.distortInverse(Math.tan(degToRad * viewer.fov)); + var fovBottom = distortion.distortInverse(Math.tan(-degToRad * viewer.fov)); + var halfWidth = device.widthMeters / 4; + var halfHeight = device.heightMeters / 2; + var verticalLensOffset = viewer.baselineLensDistance - device.bevelMeters - halfHeight; + var centerX = viewer.interLensDistance / 2 - halfWidth; + var centerY = -verticalLensOffset; + var centerZ = viewer.screenLensDistance; + var screenLeft = (centerX - halfWidth) / centerZ; + var screenTop = (centerY + halfHeight) / centerZ; + var screenRight = (centerX + halfWidth) / centerZ; + var screenBottom = (centerY - halfHeight) / centerZ; + result[0] = Math.max(fovLeft, screenLeft); + result[1] = Math.min(fovTop, screenTop); + result[2] = Math.min(fovRight, screenRight); + result[3] = Math.max(fovBottom, screenBottom); + return result; + }; + DeviceInfo.prototype.getLeftEyeVisibleScreenRect = function (undistortedFrustum) { + var viewer = this.viewer; + var device = this.device; + var dist = viewer.screenLensDistance; + var eyeX = (device.widthMeters - viewer.interLensDistance) / 2; + var eyeY = viewer.baselineLensDistance - device.bevelMeters; + var left = (undistortedFrustum[0] * dist + eyeX) / device.widthMeters; + var top = (undistortedFrustum[1] * dist + eyeY) / device.heightMeters; + var right = (undistortedFrustum[2] * dist + eyeX) / device.widthMeters; + var bottom = (undistortedFrustum[3] * dist + eyeY) / device.heightMeters; + return { + x: left, + y: bottom, + width: right - left, + height: top - bottom + }; + }; + DeviceInfo.prototype.getFieldOfViewLeftEye = function (opt_isUndistorted) { + return opt_isUndistorted ? this.getUndistortedFieldOfViewLeftEye() : this.getDistortedFieldOfViewLeftEye(); + }; + DeviceInfo.prototype.getFieldOfViewRightEye = function (opt_isUndistorted) { + var fov = this.getFieldOfViewLeftEye(opt_isUndistorted); + return { + leftDegrees: fov.rightDegrees, + rightDegrees: fov.leftDegrees, + upDegrees: fov.upDegrees, + downDegrees: fov.downDegrees + }; + }; + DeviceInfo.prototype.getUndistortedFieldOfViewLeftEye = function () { + var p = this.getUndistortedParams_(); + return { + leftDegrees: radToDeg * Math.atan(p.outerDist), + rightDegrees: radToDeg * Math.atan(p.innerDist), + downDegrees: radToDeg * Math.atan(p.bottomDist), + upDegrees: radToDeg * Math.atan(p.topDist) + }; + }; + DeviceInfo.prototype.getUndistortedViewportLeftEye = function () { + var p = this.getUndistortedParams_(); + var viewer = this.viewer; + var device = this.device; + var eyeToScreenDistance = viewer.screenLensDistance; + var screenWidth = device.widthMeters / eyeToScreenDistance; + var screenHeight = device.heightMeters / eyeToScreenDistance; + var xPxPerTanAngle = device.width / screenWidth; + var yPxPerTanAngle = device.height / screenHeight; + var x = Math.round((p.eyePosX - p.outerDist) * xPxPerTanAngle); + var y = Math.round((p.eyePosY - p.bottomDist) * yPxPerTanAngle); + return { + x: x, + y: y, + width: Math.round((p.eyePosX + p.innerDist) * xPxPerTanAngle) - x, + height: Math.round((p.eyePosY + p.topDist) * yPxPerTanAngle) - y + }; + }; + DeviceInfo.prototype.getUndistortedParams_ = function () { + var viewer = this.viewer; + var device = this.device; + var distortion = this.distortion; + var eyeToScreenDistance = viewer.screenLensDistance; + var halfLensDistance = viewer.interLensDistance / 2 / eyeToScreenDistance; + var screenWidth = device.widthMeters / eyeToScreenDistance; + var screenHeight = device.heightMeters / eyeToScreenDistance; + var eyePosX = screenWidth / 2 - halfLensDistance; + var eyePosY = (viewer.baselineLensDistance - device.bevelMeters) / eyeToScreenDistance; + var maxFov = viewer.fov; + var viewerMax = distortion.distortInverse(Math.tan(degToRad * maxFov)); + var outerDist = Math.min(eyePosX, viewerMax); + var innerDist = Math.min(halfLensDistance, viewerMax); + var bottomDist = Math.min(eyePosY, viewerMax); + var topDist = Math.min(screenHeight - eyePosY, viewerMax); + return { + outerDist: outerDist, + innerDist: innerDist, + topDist: topDist, + bottomDist: bottomDist, + eyePosX: eyePosX, + eyePosY: eyePosY + }; + }; + function CardboardViewer(params) { + this.id = params.id; + this.label = params.label; + this.fov = params.fov; + this.interLensDistance = params.interLensDistance; + this.baselineLensDistance = params.baselineLensDistance; + this.screenLensDistance = params.screenLensDistance; + this.distortionCoefficients = params.distortionCoefficients; + this.inverseCoefficients = params.inverseCoefficients; + } + DeviceInfo.Viewers = Viewers; + var format = 1; + var last_updated = "2019-11-09T17:36:14Z"; + var devices = [{ + "type": "android", + "rules": [{ + "mdmh": "asus/*/Nexus 7/*" + }, { + "ua": "Nexus 7" + }], + "dpi": [320.8, 323], + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "asus/*/ASUS_X00PD/*" + }, { + "ua": "ASUS_X00PD" + }], + "dpi": 245, + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "asus/*/ASUS_X008D/*" + }, { + "ua": "ASUS_X008D" + }], + "dpi": 282, + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "asus/*/ASUS_Z00AD/*" + }, { + "ua": "ASUS_Z00AD" + }], + "dpi": [403, 404.6], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "Google/*/Pixel 2 XL/*" + }, { + "ua": "Pixel 2 XL" + }], + "dpi": 537.9, + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "Google/*/Pixel 3 XL/*" + }, { + "ua": "Pixel 3 XL" + }], + "dpi": [558.5, 553.8], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "Google/*/Pixel XL/*" + }, { + "ua": "Pixel XL" + }], + "dpi": [537.9, 533], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "Google/*/Pixel 3/*" + }, { + "ua": "Pixel 3" + }], + "dpi": 442.4, + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "Google/*/Pixel 2/*" + }, { + "ua": "Pixel 2" + }], + "dpi": 441, + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "Google/*/Pixel/*" + }, { + "ua": "Pixel" + }], + "dpi": [432.6, 436.7], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "HTC/*/HTC6435LVW/*" + }, { + "ua": "HTC6435LVW" + }], + "dpi": [449.7, 443.3], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "HTC/*/HTC One XL/*" + }, { + "ua": "HTC One XL" + }], + "dpi": [315.3, 314.6], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "htc/*/Nexus 9/*" + }, { + "ua": "Nexus 9" + }], + "dpi": 289, + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "HTC/*/HTC One M9/*" + }, { + "ua": "HTC One M9" + }], + "dpi": [442.5, 443.3], + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "HTC/*/HTC One_M8/*" + }, { + "ua": "HTC One_M8" + }], + "dpi": [449.7, 447.4], + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "HTC/*/HTC One/*" + }, { + "ua": "HTC One" + }], + "dpi": 472.8, + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "Huawei/*/Nexus 6P/*" + }, { + "ua": "Nexus 6P" + }], + "dpi": [515.1, 518], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "Huawei/*/BLN-L24/*" + }, { + "ua": "HONORBLN-L24" + }], + "dpi": 480, + "bw": 4, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "Huawei/*/BKL-L09/*" + }, { + "ua": "BKL-L09" + }], + "dpi": 403, + "bw": 3.47, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "LENOVO/*/Lenovo PB2-690Y/*" + }, { + "ua": "Lenovo PB2-690Y" + }], + "dpi": [457.2, 454.713], + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "LGE/*/Nexus 5X/*" + }, { + "ua": "Nexus 5X" + }], + "dpi": [422, 419.9], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "LGE/*/LGMS345/*" + }, { + "ua": "LGMS345" + }], + "dpi": [221.7, 219.1], + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "LGE/*/LG-D800/*" + }, { + "ua": "LG-D800" + }], + "dpi": [422, 424.1], + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "LGE/*/LG-D850/*" + }, { + "ua": "LG-D850" + }], + "dpi": [537.9, 541.9], + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "LGE/*/VS985 4G/*" + }, { + "ua": "VS985 4G" + }], + "dpi": [537.9, 535.6], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "LGE/*/Nexus 5/*" + }, { + "ua": "Nexus 5 B" + }], + "dpi": [442.4, 444.8], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "LGE/*/Nexus 4/*" + }, { + "ua": "Nexus 4" + }], + "dpi": [319.8, 318.4], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "LGE/*/LG-P769/*" + }, { + "ua": "LG-P769" + }], + "dpi": [240.6, 247.5], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "LGE/*/LGMS323/*" + }, { + "ua": "LGMS323" + }], + "dpi": [206.6, 204.6], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "LGE/*/LGLS996/*" + }, { + "ua": "LGLS996" + }], + "dpi": [403.4, 401.5], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "Micromax/*/4560MMX/*" + }, { + "ua": "4560MMX" + }], + "dpi": [240, 219.4], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "Micromax/*/A250/*" + }, { + "ua": "Micromax A250" + }], + "dpi": [480, 446.4], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "Micromax/*/Micromax AQ4501/*" + }, { + "ua": "Micromax AQ4501" + }], + "dpi": 240, + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "motorola/*/G5/*" + }, { + "ua": "Moto G (5) Plus" + }], + "dpi": [403.4, 403], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "motorola/*/DROID RAZR/*" + }, { + "ua": "DROID RAZR" + }], + "dpi": [368.1, 256.7], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "motorola/*/XT830C/*" + }, { + "ua": "XT830C" + }], + "dpi": [254, 255.9], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "motorola/*/XT1021/*" + }, { + "ua": "XT1021" + }], + "dpi": [254, 256.7], + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "motorola/*/XT1023/*" + }, { + "ua": "XT1023" + }], + "dpi": [254, 256.7], + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "motorola/*/XT1028/*" + }, { + "ua": "XT1028" + }], + "dpi": [326.6, 327.6], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "motorola/*/XT1034/*" + }, { + "ua": "XT1034" + }], + "dpi": [326.6, 328.4], + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "motorola/*/XT1053/*" + }, { + "ua": "XT1053" + }], + "dpi": [315.3, 316.1], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "motorola/*/XT1562/*" + }, { + "ua": "XT1562" + }], + "dpi": [403.4, 402.7], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "motorola/*/Nexus 6/*" + }, { + "ua": "Nexus 6 B" + }], + "dpi": [494.3, 489.7], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "motorola/*/XT1063/*" + }, { + "ua": "XT1063" + }], + "dpi": [295, 296.6], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "motorola/*/XT1064/*" + }, { + "ua": "XT1064" + }], + "dpi": [295, 295.6], + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "motorola/*/XT1092/*" + }, { + "ua": "XT1092" + }], + "dpi": [422, 424.1], + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "motorola/*/XT1095/*" + }, { + "ua": "XT1095" + }], + "dpi": [422, 423.4], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "motorola/*/G4/*" + }, { + "ua": "Moto G (4)" + }], + "dpi": 401, + "bw": 4, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "OnePlus/*/A0001/*" + }, { + "ua": "A0001" + }], + "dpi": [403.4, 401], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "OnePlus/*/ONE E1001/*" + }, { + "ua": "ONE E1001" + }], + "dpi": [442.4, 441.4], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "OnePlus/*/ONE E1003/*" + }, { + "ua": "ONE E1003" + }], + "dpi": [442.4, 441.4], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "OnePlus/*/ONE E1005/*" + }, { + "ua": "ONE E1005" + }], + "dpi": [442.4, 441.4], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "OnePlus/*/ONE A2001/*" + }, { + "ua": "ONE A2001" + }], + "dpi": [391.9, 405.4], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "OnePlus/*/ONE A2003/*" + }, { + "ua": "ONE A2003" + }], + "dpi": [391.9, 405.4], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "OnePlus/*/ONE A2005/*" + }, { + "ua": "ONE A2005" + }], + "dpi": [391.9, 405.4], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "OnePlus/*/ONEPLUS A3000/*" + }, { + "ua": "ONEPLUS A3000" + }], + "dpi": 401, + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "OnePlus/*/ONEPLUS A3003/*" + }, { + "ua": "ONEPLUS A3003" + }], + "dpi": 401, + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "OnePlus/*/ONEPLUS A3010/*" + }, { + "ua": "ONEPLUS A3010" + }], + "dpi": 401, + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "OnePlus/*/ONEPLUS A5000/*" + }, { + "ua": "ONEPLUS A5000 " + }], + "dpi": [403.411, 399.737], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "OnePlus/*/ONE A5010/*" + }, { + "ua": "ONEPLUS A5010" + }], + "dpi": [403, 400], + "bw": 2, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "OnePlus/*/ONEPLUS A6000/*" + }, { + "ua": "ONEPLUS A6000" + }], + "dpi": 401, + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "OnePlus/*/ONEPLUS A6003/*" + }, { + "ua": "ONEPLUS A6003" + }], + "dpi": 401, + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "OnePlus/*/ONEPLUS A6010/*" + }, { + "ua": "ONEPLUS A6010" + }], + "dpi": 401, + "bw": 2, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "OnePlus/*/ONEPLUS A6013/*" + }, { + "ua": "ONEPLUS A6013" + }], + "dpi": 401, + "bw": 2, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "OPPO/*/X909/*" + }, { + "ua": "X909" + }], + "dpi": [442.4, 444.1], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/GT-I9082/*" + }, { + "ua": "GT-I9082" + }], + "dpi": [184.7, 185.4], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G360P/*" + }, { + "ua": "SM-G360P" + }], + "dpi": [196.7, 205.4], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/Nexus S/*" + }, { + "ua": "Nexus S" + }], + "dpi": [234.5, 229.8], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/GT-I9300/*" + }, { + "ua": "GT-I9300" + }], + "dpi": [304.8, 303.9], + "bw": 5, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-T230NU/*" + }, { + "ua": "SM-T230NU" + }], + "dpi": 216, + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SGH-T399/*" + }, { + "ua": "SGH-T399" + }], + "dpi": [217.7, 231.4], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SGH-M919/*" + }, { + "ua": "SGH-M919" + }], + "dpi": [440.8, 437.7], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-N9005/*" + }, { + "ua": "SM-N9005" + }], + "dpi": [386.4, 387], + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SAMSUNG-SM-N900A/*" + }, { + "ua": "SAMSUNG-SM-N900A" + }], + "dpi": [386.4, 387.7], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/GT-I9500/*" + }, { + "ua": "GT-I9500" + }], + "dpi": [442.5, 443.3], + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/GT-I9505/*" + }, { + "ua": "GT-I9505" + }], + "dpi": 439.4, + "bw": 4, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G900F/*" + }, { + "ua": "SM-G900F" + }], + "dpi": [415.6, 431.6], + "bw": 5, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G900M/*" + }, { + "ua": "SM-G900M" + }], + "dpi": [415.6, 431.6], + "bw": 5, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G800F/*" + }, { + "ua": "SM-G800F" + }], + "dpi": 326.8, + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G906S/*" + }, { + "ua": "SM-G906S" + }], + "dpi": [562.7, 572.4], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/GT-I9300/*" + }, { + "ua": "GT-I9300" + }], + "dpi": [306.7, 304.8], + "bw": 5, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-T535/*" + }, { + "ua": "SM-T535" + }], + "dpi": [142.6, 136.4], + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-N920C/*" + }, { + "ua": "SM-N920C" + }], + "dpi": [515.1, 518.4], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-N920P/*" + }, { + "ua": "SM-N920P" + }], + "dpi": [386.3655, 390.144], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-N920W8/*" + }, { + "ua": "SM-N920W8" + }], + "dpi": [515.1, 518.4], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/GT-I9300I/*" + }, { + "ua": "GT-I9300I" + }], + "dpi": [304.8, 305.8], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/GT-I9195/*" + }, { + "ua": "GT-I9195" + }], + "dpi": [249.4, 256.7], + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SPH-L520/*" + }, { + "ua": "SPH-L520" + }], + "dpi": [249.4, 255.9], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SAMSUNG-SGH-I717/*" + }, { + "ua": "SAMSUNG-SGH-I717" + }], + "dpi": 285.8, + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SPH-D710/*" + }, { + "ua": "SPH-D710" + }], + "dpi": [217.7, 204.2], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/GT-N7100/*" + }, { + "ua": "GT-N7100" + }], + "dpi": 265.1, + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SCH-I605/*" + }, { + "ua": "SCH-I605" + }], + "dpi": 265.1, + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/Galaxy Nexus/*" + }, { + "ua": "Galaxy Nexus" + }], + "dpi": [315.3, 314.2], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-N910H/*" + }, { + "ua": "SM-N910H" + }], + "dpi": [515.1, 518], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-N910C/*" + }, { + "ua": "SM-N910C" + }], + "dpi": [515.2, 520.2], + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G130M/*" + }, { + "ua": "SM-G130M" + }], + "dpi": [165.9, 164.8], + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G928I/*" + }, { + "ua": "SM-G928I" + }], + "dpi": [515.1, 518.4], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G920F/*" + }, { + "ua": "SM-G920F" + }], + "dpi": 580.6, + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G920P/*" + }, { + "ua": "SM-G920P" + }], + "dpi": [522.5, 577], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G925F/*" + }, { + "ua": "SM-G925F" + }], + "dpi": 580.6, + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G925V/*" + }, { + "ua": "SM-G925V" + }], + "dpi": [522.5, 576.6], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G930F/*" + }, { + "ua": "SM-G930F" + }], + "dpi": 576.6, + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G935F/*" + }, { + "ua": "SM-G935F" + }], + "dpi": 533, + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G950F/*" + }, { + "ua": "SM-G950F" + }], + "dpi": [562.707, 565.293], + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G955U/*" + }, { + "ua": "SM-G955U" + }], + "dpi": [522.514, 525.762], + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G955F/*" + }, { + "ua": "SM-G955F" + }], + "dpi": [522.514, 525.762], + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G960F/*" + }, { + "ua": "SM-G960F" + }], + "dpi": [569.575, 571.5], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G9600/*" + }, { + "ua": "SM-G9600" + }], + "dpi": [569.575, 571.5], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G960T/*" + }, { + "ua": "SM-G960T" + }], + "dpi": [569.575, 571.5], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G960N/*" + }, { + "ua": "SM-G960N" + }], + "dpi": [569.575, 571.5], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G960U/*" + }, { + "ua": "SM-G960U" + }], + "dpi": [569.575, 571.5], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G9608/*" + }, { + "ua": "SM-G9608" + }], + "dpi": [569.575, 571.5], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G960FD/*" + }, { + "ua": "SM-G960FD" + }], + "dpi": [569.575, 571.5], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G960W/*" + }, { + "ua": "SM-G960W" + }], + "dpi": [569.575, 571.5], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G965F/*" + }, { + "ua": "SM-G965F" + }], + "dpi": 529, + "bw": 2, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "Sony/*/C6903/*" + }, { + "ua": "C6903" + }], + "dpi": [442.5, 443.3], + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "Sony/*/D6653/*" + }, { + "ua": "D6653" + }], + "dpi": [428.6, 427.6], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "Sony/*/E6653/*" + }, { + "ua": "E6653" + }], + "dpi": [428.6, 425.7], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "Sony/*/E6853/*" + }, { + "ua": "E6853" + }], + "dpi": [403.4, 401.9], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "Sony/*/SGP321/*" + }, { + "ua": "SGP321" + }], + "dpi": [224.7, 224.1], + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "TCT/*/ALCATEL ONE TOUCH Fierce/*" + }, { + "ua": "ALCATEL ONE TOUCH Fierce" + }], + "dpi": [240, 247.5], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "THL/*/thl 5000/*" + }, { + "ua": "thl 5000" + }], + "dpi": [480, 443.3], + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "Fly/*/IQ4412/*" + }, { + "ua": "IQ4412" + }], + "dpi": 307.9, + "bw": 3, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "ZTE/*/ZTE Blade L2/*" + }, { + "ua": "ZTE Blade L2" + }], + "dpi": 240, + "bw": 3, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "BENEVE/*/VR518/*" + }, { + "ua": "VR518" + }], + "dpi": 480, + "bw": 3, + "ac": 500 + }, { + "type": "ios", + "rules": [{ + "res": [640, 960] + }], + "dpi": [325.1, 328.4], + "bw": 4, + "ac": 1000 + }, { + "type": "ios", + "rules": [{ + "res": [640, 1136] + }], + "dpi": [317.1, 320.2], + "bw": 3, + "ac": 1000 + }, { + "type": "ios", + "rules": [{ + "res": [750, 1334] + }], + "dpi": 326.4, + "bw": 4, + "ac": 1000 + }, { + "type": "ios", + "rules": [{ + "res": [1242, 2208] + }], + "dpi": [453.6, 458.4], + "bw": 4, + "ac": 1000 + }, { + "type": "ios", + "rules": [{ + "res": [1125, 2001] + }], + "dpi": [410.9, 415.4], + "bw": 4, + "ac": 1000 + }, { + "type": "ios", + "rules": [{ + "res": [1125, 2436] + }], + "dpi": 458, + "bw": 4, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "Huawei/*/EML-L29/*" + }, { + "ua": "EML-L29" + }], + "dpi": 428, + "bw": 3.45, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "Nokia/*/Nokia 7.1/*" + }, { + "ua": "Nokia 7.1" + }], + "dpi": [432, 431.9], + "bw": 3, + "ac": 500 + }, { + "type": "ios", + "rules": [{ + "res": [1242, 2688] + }], + "dpi": 458, + "bw": 4, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G570M/*" + }, { + "ua": "SM-G570M" + }], + "dpi": 320, + "bw": 3.684, + "ac": 1000 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G970F/*" + }, { + "ua": "SM-G970F" + }], + "dpi": 438, + "bw": 2.281, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G973F/*" + }, { + "ua": "SM-G973F" + }], + "dpi": 550, + "bw": 2.002, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G975F/*" + }, { + "ua": "SM-G975F" + }], + "dpi": 522, + "bw": 2.054, + "ac": 500 + }, { + "type": "android", + "rules": [{ + "mdmh": "samsung/*/SM-G977F/*" + }, { + "ua": "SM-G977F" + }], + "dpi": 505, + "bw": 2.334, + "ac": 500 + }, { + "type": "ios", + "rules": [{ + "res": [828, 1792] + }], + "dpi": 326, + "bw": 5, + "ac": 500 + }]; + var DPDB_CACHE = { + format: format, + last_updated: last_updated, + devices: devices + }; + function Dpdb(url, onDeviceParamsUpdated) { + this.dpdb = DPDB_CACHE; + this.recalculateDeviceParams_(); + if (url) { + this.onDeviceParamsUpdated = onDeviceParamsUpdated; + var xhr = new XMLHttpRequest(); + var obj = this; + xhr.open('GET', url, true); + xhr.addEventListener('load', function () { + obj.loading = false; + if (xhr.status >= 200 && xhr.status <= 299) { + obj.dpdb = JSON.parse(xhr.response); + obj.recalculateDeviceParams_(); + } else { + console.error('Error loading online DPDB!'); + } + }); + xhr.send(); + } + } + Dpdb.prototype.getDeviceParams = function () { + return this.deviceParams; + }; + Dpdb.prototype.recalculateDeviceParams_ = function () { + var newDeviceParams = this.calcDeviceParams_(); + if (newDeviceParams) { + this.deviceParams = newDeviceParams; + if (this.onDeviceParamsUpdated) { + this.onDeviceParamsUpdated(this.deviceParams); + } + } else { + console.error('Failed to recalculate device parameters.'); + } + }; + Dpdb.prototype.calcDeviceParams_ = function () { + var db = this.dpdb; + if (!db) { + console.error('DPDB not available.'); + return null; + } + if (db.format != 1) { + console.error('DPDB has unexpected format version.'); + return null; + } + if (!db.devices || !db.devices.length) { + console.error('DPDB does not have a devices section.'); + return null; + } + var userAgent = navigator.userAgent || navigator.vendor || window.opera; + var width = getScreenWidth(); + var height = getScreenHeight(); + if (!db.devices) { + console.error('DPDB has no devices section.'); + return null; + } + for (var i = 0; i < db.devices.length; i++) { + var device = db.devices[i]; + if (!device.rules) { + console.warn('Device[' + i + '] has no rules section.'); + continue; + } + if (device.type != 'ios' && device.type != 'android') { + console.warn('Device[' + i + '] has invalid type.'); + continue; + } + if (isIOS() != (device.type == 'ios')) continue; + var matched = false; + for (var j = 0; j < device.rules.length; j++) { + var rule = device.rules[j]; + if (this.ruleMatches_(rule, userAgent, width, height)) { + matched = true; + break; + } + } + if (!matched) continue; + var xdpi = device.dpi[0] || device.dpi; + var ydpi = device.dpi[1] || device.dpi; + return new DeviceParams({ + xdpi: xdpi, + ydpi: ydpi, + bevelMm: device.bw + }); + } + console.warn('No DPDB device match.'); + return null; + }; + Dpdb.prototype.ruleMatches_ = function (rule, ua, screenWidth, screenHeight) { + if (!rule.ua && !rule.res) return false; + if (rule.ua && rule.ua.substring(0, 2) === 'SM') rule.ua = rule.ua.substring(0, 7); + if (rule.ua && ua.indexOf(rule.ua) < 0) return false; + if (rule.res) { + if (!rule.res[0] || !rule.res[1]) return false; + var resX = rule.res[0]; + var resY = rule.res[1]; + if (Math.min(screenWidth, screenHeight) != Math.min(resX, resY) || Math.max(screenWidth, screenHeight) != Math.max(resX, resY)) { + return false; + } + } + return true; + }; + function DeviceParams(params) { + this.xdpi = params.xdpi; + this.ydpi = params.ydpi; + this.bevelMm = params.bevelMm; + } + function SensorSample(sample, timestampS) { + this.set(sample, timestampS); + } + SensorSample.prototype.set = function (sample, timestampS) { + this.sample = sample; + this.timestampS = timestampS; + }; + SensorSample.prototype.copy = function (sensorSample) { + this.set(sensorSample.sample, sensorSample.timestampS); + }; + function ComplementaryFilter(kFilter, isDebug) { + this.kFilter = kFilter; + this.isDebug = isDebug; + this.currentAccelMeasurement = new SensorSample(); + this.currentGyroMeasurement = new SensorSample(); + this.previousGyroMeasurement = new SensorSample(); + if (isIOS()) { + this.filterQ = new Quaternion(-1, 0, 0, 1); + } else { + this.filterQ = new Quaternion(1, 0, 0, 1); + } + this.previousFilterQ = new Quaternion(); + this.previousFilterQ.copy(this.filterQ); + this.accelQ = new Quaternion(); + this.isOrientationInitialized = false; + this.estimatedGravity = new Vector3(); + this.measuredGravity = new Vector3(); + this.gyroIntegralQ = new Quaternion(); + } + ComplementaryFilter.prototype.addAccelMeasurement = function (vector, timestampS) { + this.currentAccelMeasurement.set(vector, timestampS); + }; + ComplementaryFilter.prototype.addGyroMeasurement = function (vector, timestampS) { + this.currentGyroMeasurement.set(vector, timestampS); + var deltaT = timestampS - this.previousGyroMeasurement.timestampS; + if (isTimestampDeltaValid(deltaT)) { + this.run_(); + } + this.previousGyroMeasurement.copy(this.currentGyroMeasurement); + }; + ComplementaryFilter.prototype.run_ = function () { + if (!this.isOrientationInitialized) { + this.accelQ = this.accelToQuaternion_(this.currentAccelMeasurement.sample); + this.previousFilterQ.copy(this.accelQ); + this.isOrientationInitialized = true; + return; + } + var deltaT = this.currentGyroMeasurement.timestampS - this.previousGyroMeasurement.timestampS; + var gyroDeltaQ = this.gyroToQuaternionDelta_(this.currentGyroMeasurement.sample, deltaT); + this.gyroIntegralQ.multiply(gyroDeltaQ); + this.filterQ.copy(this.previousFilterQ); + this.filterQ.multiply(gyroDeltaQ); + var invFilterQ = new Quaternion(); + invFilterQ.copy(this.filterQ); + invFilterQ.inverse(); + this.estimatedGravity.set(0, 0, -1); + this.estimatedGravity.applyQuaternion(invFilterQ); + this.estimatedGravity.normalize(); + this.measuredGravity.copy(this.currentAccelMeasurement.sample); + this.measuredGravity.normalize(); + var deltaQ = new Quaternion(); + deltaQ.setFromUnitVectors(this.estimatedGravity, this.measuredGravity); + deltaQ.inverse(); + if (this.isDebug) { + console.log('Delta: %d deg, G_est: (%s, %s, %s), G_meas: (%s, %s, %s)', radToDeg * getQuaternionAngle(deltaQ), this.estimatedGravity.x.toFixed(1), this.estimatedGravity.y.toFixed(1), this.estimatedGravity.z.toFixed(1), this.measuredGravity.x.toFixed(1), this.measuredGravity.y.toFixed(1), this.measuredGravity.z.toFixed(1)); + } + var targetQ = new Quaternion(); + targetQ.copy(this.filterQ); + targetQ.multiply(deltaQ); + this.filterQ.slerp(targetQ, 1 - this.kFilter); + this.previousFilterQ.copy(this.filterQ); + }; + ComplementaryFilter.prototype.getOrientation = function () { + return this.filterQ; + }; + ComplementaryFilter.prototype.accelToQuaternion_ = function (accel) { + var normAccel = new Vector3(); + normAccel.copy(accel); + normAccel.normalize(); + var quat = new Quaternion(); + quat.setFromUnitVectors(new Vector3(0, 0, -1), normAccel); + quat.inverse(); + return quat; + }; + ComplementaryFilter.prototype.gyroToQuaternionDelta_ = function (gyro, dt) { + var quat = new Quaternion(); + var axis = new Vector3(); + axis.copy(gyro); + axis.normalize(); + quat.setFromAxisAngle(axis, gyro.length() * dt); + return quat; + }; + function PosePredictor(predictionTimeS, isDebug) { + this.predictionTimeS = predictionTimeS; + this.isDebug = isDebug; + this.previousQ = new Quaternion(); + this.previousTimestampS = null; + this.deltaQ = new Quaternion(); + this.outQ = new Quaternion(); + } + PosePredictor.prototype.getPrediction = function (currentQ, gyro, timestampS) { + if (!this.previousTimestampS) { + this.previousQ.copy(currentQ); + this.previousTimestampS = timestampS; + return currentQ; + } + var axis = new Vector3(); + axis.copy(gyro); + axis.normalize(); + var angularSpeed = gyro.length(); + if (angularSpeed < degToRad * 20) { + if (this.isDebug) { + console.log('Moving slowly, at %s deg/s: no prediction', (radToDeg * angularSpeed).toFixed(1)); + } + this.outQ.copy(currentQ); + this.previousQ.copy(currentQ); + return this.outQ; + } + var predictAngle = angularSpeed * this.predictionTimeS; + this.deltaQ.setFromAxisAngle(axis, predictAngle); + this.outQ.copy(this.previousQ); + this.outQ.multiply(this.deltaQ); + this.previousQ.copy(currentQ); + this.previousTimestampS = timestampS; + return this.outQ; + }; + function FusionPoseSensor(kFilter, predictionTime, yawOnly, isDebug) { + this.yawOnly = yawOnly; + this.accelerometer = new Vector3(); + this.gyroscope = new Vector3(); + this.filter = new ComplementaryFilter(kFilter, isDebug); + this.posePredictor = new PosePredictor(predictionTime, isDebug); + this.isFirefoxAndroid = isFirefoxAndroid(); + this.isIOS = isIOS(); + var chromeVersion = getChromeVersion(); + this.isDeviceMotionInRadians = !this.isIOS && chromeVersion && chromeVersion < 66; + this.isWithoutDeviceMotion = isChromeWithoutDeviceMotion() || isSafariWithoutDeviceMotion(); + this.filterToWorldQ = new Quaternion(); + if (isIOS()) { + this.filterToWorldQ.setFromAxisAngle(new Vector3(1, 0, 0), Math.PI / 2); + } else { + this.filterToWorldQ.setFromAxisAngle(new Vector3(1, 0, 0), -Math.PI / 2); + } + this.inverseWorldToScreenQ = new Quaternion(); + this.worldToScreenQ = new Quaternion(); + this.originalPoseAdjustQ = new Quaternion(); + this.originalPoseAdjustQ.setFromAxisAngle(new Vector3(0, 0, 1), -window.orientation * Math.PI / 180); + this.setScreenTransform_(); + if (isLandscapeMode()) { + this.filterToWorldQ.multiply(this.inverseWorldToScreenQ); + } + this.resetQ = new Quaternion(); + this.orientationOut_ = new Float32Array(4); + this.start(); + } + FusionPoseSensor.prototype.getPosition = function () { + return null; + }; + FusionPoseSensor.prototype.getOrientation = function () { + var orientation = void 0; + if (this.isWithoutDeviceMotion && this._deviceOrientationQ) { + this.deviceOrientationFixQ = this.deviceOrientationFixQ || function () { + var z = new Quaternion().setFromAxisAngle(new Vector3(0, 0, -1), 0); + var y = new Quaternion(); + if (window.orientation === -90) { + y.setFromAxisAngle(new Vector3(0, 1, 0), Math.PI / -2); + } else { + y.setFromAxisAngle(new Vector3(0, 1, 0), Math.PI / 2); + } + return z.multiply(y); + }(); + this.deviceOrientationFilterToWorldQ = this.deviceOrientationFilterToWorldQ || function () { + var q = new Quaternion(); + q.setFromAxisAngle(new Vector3(1, 0, 0), -Math.PI / 2); + return q; + }(); + orientation = this._deviceOrientationQ; + var out = new Quaternion(); + out.copy(orientation); + out.multiply(this.deviceOrientationFilterToWorldQ); + out.multiply(this.resetQ); + out.multiply(this.worldToScreenQ); + out.multiplyQuaternions(this.deviceOrientationFixQ, out); + if (this.yawOnly) { + out.x = 0; + out.z = 0; + out.normalize(); + } + this.orientationOut_[0] = out.x; + this.orientationOut_[1] = out.y; + this.orientationOut_[2] = out.z; + this.orientationOut_[3] = out.w; + return this.orientationOut_; + } else { + var filterOrientation = this.filter.getOrientation(); + orientation = this.posePredictor.getPrediction(filterOrientation, this.gyroscope, this.previousTimestampS); + } + var out = new Quaternion(); + out.copy(this.filterToWorldQ); + out.multiply(this.resetQ); + out.multiply(orientation); + out.multiply(this.worldToScreenQ); + if (this.yawOnly) { + out.x = 0; + out.z = 0; + out.normalize(); + } + this.orientationOut_[0] = out.x; + this.orientationOut_[1] = out.y; + this.orientationOut_[2] = out.z; + this.orientationOut_[3] = out.w; + return this.orientationOut_; + }; + FusionPoseSensor.prototype.resetPose = function () { + this.resetQ.copy(this.filter.getOrientation()); + this.resetQ.x = 0; + this.resetQ.y = 0; + this.resetQ.z *= -1; + this.resetQ.normalize(); + if (isLandscapeMode()) { + this.resetQ.multiply(this.inverseWorldToScreenQ); + } + this.resetQ.multiply(this.originalPoseAdjustQ); + }; + FusionPoseSensor.prototype.onDeviceOrientation_ = function (e) { + this._deviceOrientationQ = this._deviceOrientationQ || new Quaternion(); + var alpha = e.alpha, + beta = e.beta, + gamma = e.gamma; + alpha = (alpha || 0) * Math.PI / 180; + beta = (beta || 0) * Math.PI / 180; + gamma = (gamma || 0) * Math.PI / 180; + this._deviceOrientationQ.setFromEulerYXZ(beta, alpha, -gamma); + }; + FusionPoseSensor.prototype.onDeviceMotion_ = function (deviceMotion) { + this.updateDeviceMotion_(deviceMotion); + }; + FusionPoseSensor.prototype.updateDeviceMotion_ = function (deviceMotion) { + var accGravity = deviceMotion.accelerationIncludingGravity; + var rotRate = deviceMotion.rotationRate; + var timestampS = deviceMotion.timeStamp / 1000; + var deltaS = timestampS - this.previousTimestampS; + if (deltaS < 0) { + warnOnce('fusion-pose-sensor:invalid:non-monotonic', 'Invalid timestamps detected: non-monotonic timestamp from devicemotion'); + this.previousTimestampS = timestampS; + return; + } else if (deltaS <= MIN_TIMESTEP || deltaS > MAX_TIMESTEP) { + warnOnce('fusion-pose-sensor:invalid:outside-threshold', 'Invalid timestamps detected: Timestamp from devicemotion outside expected range.'); + this.previousTimestampS = timestampS; + return; + } + this.accelerometer.set(-accGravity.x, -accGravity.y, -accGravity.z); + if (rotRate) { + if (isR7()) { + this.gyroscope.set(-rotRate.beta, rotRate.alpha, rotRate.gamma); + } else { + this.gyroscope.set(rotRate.alpha, rotRate.beta, rotRate.gamma); + } + if (!this.isDeviceMotionInRadians) { + this.gyroscope.multiplyScalar(Math.PI / 180); + } + this.filter.addGyroMeasurement(this.gyroscope, timestampS); + } + this.filter.addAccelMeasurement(this.accelerometer, timestampS); + this.previousTimestampS = timestampS; + }; + FusionPoseSensor.prototype.onOrientationChange_ = function (screenOrientation) { + this.setScreenTransform_(); + }; + FusionPoseSensor.prototype.onMessage_ = function (event) { + var message = event.data; + if (!message || !message.type) { + return; + } + var type = message.type.toLowerCase(); + if (type !== 'devicemotion') { + return; + } + this.updateDeviceMotion_(message.deviceMotionEvent); + }; + FusionPoseSensor.prototype.setScreenTransform_ = function () { + this.worldToScreenQ.set(0, 0, 0, 1); + switch (window.orientation) { + case 0: + break; + case 90: + this.worldToScreenQ.setFromAxisAngle(new Vector3(0, 0, 1), -Math.PI / 2); + break; + case -90: + this.worldToScreenQ.setFromAxisAngle(new Vector3(0, 0, 1), Math.PI / 2); + break; + case 180: + break; + } + this.inverseWorldToScreenQ.copy(this.worldToScreenQ); + this.inverseWorldToScreenQ.inverse(); + }; + FusionPoseSensor.prototype.start = function () { + this.onDeviceMotionCallback_ = this.onDeviceMotion_.bind(this); + this.onOrientationChangeCallback_ = this.onOrientationChange_.bind(this); + this.onMessageCallback_ = this.onMessage_.bind(this); + this.onDeviceOrientationCallback_ = this.onDeviceOrientation_.bind(this); + if (isIOS() && isInsideCrossOriginIFrame()) { + window.addEventListener('message', this.onMessageCallback_); + } + window.addEventListener('orientationchange', this.onOrientationChangeCallback_); + if (this.isWithoutDeviceMotion) { + window.addEventListener('deviceorientation', this.onDeviceOrientationCallback_); + } else { + window.addEventListener('devicemotion', this.onDeviceMotionCallback_); + } + }; + FusionPoseSensor.prototype.stop = function () { + window.removeEventListener('devicemotion', this.onDeviceMotionCallback_); + window.removeEventListener('deviceorientation', this.onDeviceOrientationCallback_); + window.removeEventListener('orientationchange', this.onOrientationChangeCallback_); + window.removeEventListener('message', this.onMessageCallback_); + }; + var SENSOR_FREQUENCY = 60; + var X_AXIS = new Vector3(1, 0, 0); + var Z_AXIS = new Vector3(0, 0, 1); + var SENSOR_TO_VR = new Quaternion(); + SENSOR_TO_VR.setFromAxisAngle(X_AXIS, -Math.PI / 2); + SENSOR_TO_VR.multiply(new Quaternion().setFromAxisAngle(Z_AXIS, Math.PI / 2)); + var PoseSensor = function () { + function PoseSensor(config) { + classCallCheck(this, PoseSensor); + this.config = config; + this.sensor = null; + this.fusionSensor = null; + this._out = new Float32Array(4); + this.api = null; + this.errors = []; + this._sensorQ = new Quaternion(); + this._outQ = new Quaternion(); + this._onSensorRead = this._onSensorRead.bind(this); + this._onSensorError = this._onSensorError.bind(this); + this.init(); + } + createClass(PoseSensor, [{ + key: 'init', + value: function init() { + var sensor = null; + try { + sensor = new RelativeOrientationSensor({ + frequency: SENSOR_FREQUENCY, + referenceFrame: 'screen' + }); + sensor.addEventListener('error', this._onSensorError); + } catch (error) { + this.errors.push(error); + if (error.name === 'SecurityError') { + console.error('Cannot construct sensors due to the Feature Policy'); + console.warn('Attempting to fall back using "devicemotion"; however this will ' + 'fail in the future without correct permissions.'); + this.useDeviceMotion(); + } else if (error.name === 'ReferenceError') { + this.useDeviceMotion(); + } else { + console.error(error); + } + } + if (sensor) { + this.api = 'sensor'; + this.sensor = sensor; + this.sensor.addEventListener('reading', this._onSensorRead); + this.sensor.start(); + } + } + }, { + key: 'useDeviceMotion', + value: function useDeviceMotion() { + this.api = 'devicemotion'; + this.fusionSensor = new FusionPoseSensor(this.config.K_FILTER, this.config.PREDICTION_TIME_S, this.config.YAW_ONLY, this.config.DEBUG); + if (this.sensor) { + this.sensor.removeEventListener('reading', this._onSensorRead); + this.sensor.removeEventListener('error', this._onSensorError); + this.sensor = null; + } + } + }, { + key: 'getOrientation', + value: function getOrientation() { + if (this.fusionSensor) { + return this.fusionSensor.getOrientation(); + } + if (!this.sensor || !this.sensor.quaternion) { + this._out[0] = this._out[1] = this._out[2] = 0; + this._out[3] = 1; + return this._out; + } + var q = this.sensor.quaternion; + this._sensorQ.set(q[0], q[1], q[2], q[3]); + var out = this._outQ; + out.copy(SENSOR_TO_VR); + out.multiply(this._sensorQ); + if (this.config.YAW_ONLY) { + out.x = out.z = 0; + out.normalize(); + } + this._out[0] = out.x; + this._out[1] = out.y; + this._out[2] = out.z; + this._out[3] = out.w; + return this._out; + } + }, { + key: '_onSensorError', + value: function _onSensorError(event) { + this.errors.push(event.error); + if (event.error.name === 'NotAllowedError') { + console.error('Permission to access sensor was denied'); + } else if (event.error.name === 'NotReadableError') { + console.error('Sensor could not be read'); + } else { + console.error(event.error); + } + this.useDeviceMotion(); + } + }, { + key: '_onSensorRead', + value: function _onSensorRead() {} + }]); + return PoseSensor; + }(); + var rotateInstructionsAsset = ""; + function RotateInstructions() { + this.loadIcon_(); + var overlay = document.createElement('div'); + var s = overlay.style; + s.position = 'fixed'; + s.top = 0; + s.right = 0; + s.bottom = 0; + s.left = 0; + s.backgroundColor = 'gray'; + s.fontFamily = 'sans-serif'; + s.zIndex = 1000000; + var img = document.createElement('img'); + img.src = this.icon; + var s = img.style; + s.marginLeft = '25%'; + s.marginTop = '25%'; + s.width = '50%'; + overlay.appendChild(img); + var text = document.createElement('div'); + var s = text.style; + s.textAlign = 'center'; + s.fontSize = '16px'; + s.lineHeight = '24px'; + s.margin = '24px 25%'; + s.width = '50%'; + text.innerHTML = 'Place your phone into your Cardboard viewer.'; + overlay.appendChild(text); + var snackbar = document.createElement('div'); + var s = snackbar.style; + s.backgroundColor = '#CFD8DC'; + s.position = 'fixed'; + s.bottom = 0; + s.width = '100%'; + s.height = '48px'; + s.padding = '14px 24px'; + s.boxSizing = 'border-box'; + s.color = '#656A6B'; + overlay.appendChild(snackbar); + var snackbarText = document.createElement('div'); + snackbarText.style.float = 'left'; + snackbarText.innerHTML = 'No Cardboard viewer?'; + var snackbarButton = document.createElement('a'); + snackbarButton.href = 'https://www.google.com/get/cardboard/get-cardboard/'; + snackbarButton.innerHTML = 'get one'; + snackbarButton.target = '_blank'; + var s = snackbarButton.style; + s.float = 'right'; + s.fontWeight = 600; + s.textTransform = 'uppercase'; + s.borderLeft = '1px solid gray'; + s.paddingLeft = '24px'; + s.textDecoration = 'none'; + s.color = '#656A6B'; + snackbar.appendChild(snackbarText); + snackbar.appendChild(snackbarButton); + this.overlay = overlay; + this.text = text; + this.hide(); + } + RotateInstructions.prototype.show = function (parent) { + if (!parent && !this.overlay.parentElement) { + document.body.appendChild(this.overlay); + } else if (parent) { + if (this.overlay.parentElement && this.overlay.parentElement != parent) this.overlay.parentElement.removeChild(this.overlay); + parent.appendChild(this.overlay); + } + this.overlay.style.display = 'block'; + var img = this.overlay.querySelector('img'); + var s = img.style; + if (isLandscapeMode()) { + s.width = '20%'; + s.marginLeft = '40%'; + s.marginTop = '3%'; + } else { + s.width = '50%'; + s.marginLeft = '25%'; + s.marginTop = '25%'; + } + }; + RotateInstructions.prototype.hide = function () { + this.overlay.style.display = 'none'; + }; + RotateInstructions.prototype.showTemporarily = function (ms, parent) { + this.show(parent); + this.timer = setTimeout(this.hide.bind(this), ms); + }; + RotateInstructions.prototype.disableShowTemporarily = function () { + clearTimeout(this.timer); + }; + RotateInstructions.prototype.update = function () { + this.disableShowTemporarily(); + if (!isLandscapeMode() && isMobile()) { + this.show(); + } else { + this.hide(); + } + }; + RotateInstructions.prototype.loadIcon_ = function () { + this.icon = dataUri('image/svg+xml', rotateInstructionsAsset); + }; + var DEFAULT_VIEWER = 'CardboardV1'; + var VIEWER_KEY = 'WEBVR_CARDBOARD_VIEWER'; + var CLASS_NAME = 'webvr-polyfill-viewer-selector'; + function ViewerSelector(defaultViewer) { + try { + this.selectedKey = localStorage.getItem(VIEWER_KEY); + } catch (error) { + console.error('Failed to load viewer profile: %s', error); + } + if (!this.selectedKey) { + this.selectedKey = defaultViewer || DEFAULT_VIEWER; + } + this.dialog = this.createDialog_(DeviceInfo.Viewers); + this.root = null; + this.onChangeCallbacks_ = []; + } + ViewerSelector.prototype.show = function (root) { + this.root = root; + root.appendChild(this.dialog); + var selected = this.dialog.querySelector('#' + this.selectedKey); + selected.checked = true; + this.dialog.style.display = 'block'; + }; + ViewerSelector.prototype.hide = function () { + if (this.root && this.root.contains(this.dialog)) { + this.root.removeChild(this.dialog); + } + this.dialog.style.display = 'none'; + }; + ViewerSelector.prototype.getCurrentViewer = function () { + return DeviceInfo.Viewers[this.selectedKey]; + }; + ViewerSelector.prototype.getSelectedKey_ = function () { + var input = this.dialog.querySelector('input[name=field]:checked'); + if (input) { + return input.id; + } + return null; + }; + ViewerSelector.prototype.onChange = function (cb) { + this.onChangeCallbacks_.push(cb); + }; + ViewerSelector.prototype.fireOnChange_ = function (viewer) { + for (var i = 0; i < this.onChangeCallbacks_.length; i++) { + this.onChangeCallbacks_[i](viewer); + } + }; + ViewerSelector.prototype.onSave_ = function () { + this.selectedKey = this.getSelectedKey_(); + if (!this.selectedKey || !DeviceInfo.Viewers[this.selectedKey]) { + console.error('ViewerSelector.onSave_: this should never happen!'); + return; + } + this.fireOnChange_(DeviceInfo.Viewers[this.selectedKey]); + try { + localStorage.setItem(VIEWER_KEY, this.selectedKey); + } catch (error) { + console.error('Failed to save viewer profile: %s', error); + } + this.hide(); + }; + ViewerSelector.prototype.createDialog_ = function (options) { + var container = document.createElement('div'); + container.classList.add(CLASS_NAME); + container.style.display = 'none'; + var overlay = document.createElement('div'); + var s = overlay.style; + s.position = 'fixed'; + s.left = 0; + s.top = 0; + s.width = '100%'; + s.height = '100%'; + s.background = 'rgba(0, 0, 0, 0.3)'; + overlay.addEventListener('click', this.hide.bind(this)); + var width = 280; + var dialog = document.createElement('div'); + var s = dialog.style; + s.boxSizing = 'border-box'; + s.position = 'fixed'; + s.top = '24px'; + s.left = '50%'; + s.marginLeft = -width / 2 + 'px'; + s.width = width + 'px'; + s.padding = '24px'; + s.overflow = 'hidden'; + s.background = '#fafafa'; + s.fontFamily = "'Roboto', sans-serif"; + s.boxShadow = '0px 5px 20px #666'; + dialog.appendChild(this.createH1_('Select your viewer')); + for (var id in options) { + dialog.appendChild(this.createChoice_(id, options[id].label)); + } + dialog.appendChild(this.createButton_('Save', this.onSave_.bind(this))); + container.appendChild(overlay); + container.appendChild(dialog); + return container; + }; + ViewerSelector.prototype.createH1_ = function (name) { + var h1 = document.createElement('h1'); + var s = h1.style; + s.color = 'black'; + s.fontSize = '20px'; + s.fontWeight = 'bold'; + s.marginTop = 0; + s.marginBottom = '24px'; + h1.innerHTML = name; + return h1; + }; + ViewerSelector.prototype.createChoice_ = function (id, name) { + var div = document.createElement('div'); + div.style.marginTop = '8px'; + div.style.color = 'black'; + var input = document.createElement('input'); + input.style.fontSize = '30px'; + input.setAttribute('id', id); + input.setAttribute('type', 'radio'); + input.setAttribute('value', id); + input.setAttribute('name', 'field'); + var label = document.createElement('label'); + label.style.marginLeft = '4px'; + label.setAttribute('for', id); + label.innerHTML = name; + div.appendChild(input); + div.appendChild(label); + return div; + }; + ViewerSelector.prototype.createButton_ = function (label, onclick) { + var button = document.createElement('button'); + button.innerHTML = label; + var s = button.style; + s.float = 'right'; + s.textTransform = 'uppercase'; + s.color = '#1094f7'; + s.fontSize = '14px'; + s.letterSpacing = 0; + s.border = 0; + s.background = 'none'; + s.marginTop = '16px'; + button.addEventListener('click', onclick); + return button; + }; + var commonjsGlobal$$1 = typeof window !== 'undefined' ? window : typeof commonjsGlobal !== 'undefined' ? commonjsGlobal : typeof self !== 'undefined' ? self : {}; + function unwrapExports$$1(x) { + return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; + } + function createCommonjsModule$$1(fn, module) { + return module = { + exports: {} + }, fn(module, module.exports), module.exports; + } + var NoSleep = createCommonjsModule$$1(function (module, exports) { + (function webpackUniversalModuleDefinition(root, factory) { + module.exports = factory(); + })(commonjsGlobal$$1, function () { + return function (modules) { + var installedModules = {}; + function __nested_webpack_require_167216__(moduleId) { + if (installedModules[moduleId]) { + return installedModules[moduleId].exports; + } + var module = installedModules[moduleId] = { + i: moduleId, + l: false, + exports: {} + }; + modules[moduleId].call(module.exports, module, module.exports, __nested_webpack_require_167216__); + module.l = true; + return module.exports; + } + __nested_webpack_require_167216__.m = modules; + __nested_webpack_require_167216__.c = installedModules; + __nested_webpack_require_167216__.d = function (exports, name, getter) { + if (!__nested_webpack_require_167216__.o(exports, name)) { + Object.defineProperty(exports, name, { + configurable: false, + enumerable: true, + get: getter + }); + } + }; + __nested_webpack_require_167216__.n = function (module) { + var getter = module && module.__esModule ? function getDefault() { + return module['default']; + } : function getModuleExports() { + return module; + }; + __nested_webpack_require_167216__.d(getter, 'a', getter); + return getter; + }; + __nested_webpack_require_167216__.o = function (object, property) { + return Object.prototype.hasOwnProperty.call(object, property); + }; + __nested_webpack_require_167216__.p = ""; + return __nested_webpack_require_167216__(__nested_webpack_require_167216__.s = 0); + }([function (module, exports, __nested_webpack_require_168841__) { + var _createClass = function () { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function (Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + var mediaFile = __nested_webpack_require_168841__(1); + var oldIOS = typeof navigator !== 'undefined' && parseFloat(('' + (/CPU.*OS ([0-9_]{3,4})[0-9_]{0,1}|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent) || [0, ''])[1]).replace('undefined', '3_2').replace('_', '.').replace('_', '')) < 10 && !window.MSStream; + var NoSleep = function () { + function NoSleep() { + _classCallCheck(this, NoSleep); + if (oldIOS) { + this.noSleepTimer = null; + } else { + this.noSleepVideo = document.createElement('video'); + this.noSleepVideo.setAttribute('playsinline', ''); + this.noSleepVideo.setAttribute('src', mediaFile); + this.noSleepVideo.addEventListener('timeupdate', function (e) { + if (this.noSleepVideo.currentTime > 0.5) { + this.noSleepVideo.currentTime = Math.random(); + } + }.bind(this)); + } + } + _createClass(NoSleep, [{ + key: 'enable', + value: function enable() { + if (oldIOS) { + this.disable(); + this.noSleepTimer = window.setInterval(function () { + window.location.href = '/'; + window.setTimeout(window.stop, 0); + }, 15000); + } else { + this.noSleepVideo.play(); + } + } + }, { + key: 'disable', + value: function disable() { + if (oldIOS) { + if (this.noSleepTimer) { + window.clearInterval(this.noSleepTimer); + this.noSleepTimer = null; + } + } else { + this.noSleepVideo.pause(); + } + } + }]); + return NoSleep; + }(); + module.exports = NoSleep; + }, function (module, exports, __webpack_require__) { + module.exports = 'data:video/mp4;base64,AAAAIGZ0eXBtcDQyAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQAACKBtZGF0AAAC8wYF///v3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE0MiByMjQ3OSBkZDc5YTYxIC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMjAxNCAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYmFjPTEgcmVmPTEgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MToweDExMSBtZT1oZXggc3VibWU9MiBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0wIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MCA4eDhkY3Q9MCBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0wIHRocmVhZHM9NiBsb29rYWhlYWRfdGhyZWFkcz0xIHNsaWNlZF90aHJlYWRzPTAgbnI9MCBkZWNpbWF0ZT0xIGludGVybGFjZWQ9MCBibHVyYXlfY29tcGF0PTAgY29uc3RyYWluZWRfaW50cmE9MCBiZnJhbWVzPTMgYl9weXJhbWlkPTIgYl9hZGFwdD0xIGJfYmlhcz0wIGRpcmVjdD0xIHdlaWdodGI9MSBvcGVuX2dvcD0wIHdlaWdodHA9MSBrZXlpbnQ9MzAwIGtleWludF9taW49MzAgc2NlbmVjdXQ9NDAgaW50cmFfcmVmcmVzaD0wIHJjX2xvb2thaGVhZD0xMCByYz1jcmYgbWJ0cmVlPTEgY3JmPTIwLjAgcWNvbXA9MC42MCBxcG1pbj0wIHFwbWF4PTY5IHFwc3RlcD00IHZidl9tYXhyYXRlPTIwMDAwIHZidl9idWZzaXplPTI1MDAwIGNyZl9tYXg9MC4wIG5hbF9ocmQ9bm9uZSBmaWxsZXI9MCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAAOWWIhAA3//p+C7v8tDDSTjf97w55i3SbRPO4ZY+hkjD5hbkAkL3zpJ6h/LR1CAABzgB1kqqzUorlhQAAAAxBmiQYhn/+qZYADLgAAAAJQZ5CQhX/AAj5IQADQGgcIQADQGgcAAAACQGeYUQn/wALKCEAA0BoHAAAAAkBnmNEJ/8ACykhAANAaBwhAANAaBwAAAANQZpoNExDP/6plgAMuSEAA0BoHAAAAAtBnoZFESwr/wAI+SEAA0BoHCEAA0BoHAAAAAkBnqVEJ/8ACykhAANAaBwAAAAJAZ6nRCf/AAsoIQADQGgcIQADQGgcAAAADUGarDRMQz/+qZYADLghAANAaBwAAAALQZ7KRRUsK/8ACPkhAANAaBwAAAAJAZ7pRCf/AAsoIQADQGgcIQADQGgcAAAACQGe60Qn/wALKCEAA0BoHAAAAA1BmvA0TEM//qmWAAy5IQADQGgcIQADQGgcAAAAC0GfDkUVLCv/AAj5IQADQGgcAAAACQGfLUQn/wALKSEAA0BoHCEAA0BoHAAAAAkBny9EJ/8ACyghAANAaBwAAAANQZs0NExDP/6plgAMuCEAA0BoHAAAAAtBn1JFFSwr/wAI+SEAA0BoHCEAA0BoHAAAAAkBn3FEJ/8ACyghAANAaBwAAAAJAZ9zRCf/AAsoIQADQGgcIQADQGgcAAAADUGbeDRMQz/+qZYADLkhAANAaBwAAAALQZ+WRRUsK/8ACPghAANAaBwhAANAaBwAAAAJAZ+1RCf/AAspIQADQGgcAAAACQGft0Qn/wALKSEAA0BoHCEAA0BoHAAAAA1Bm7w0TEM//qmWAAy4IQADQGgcAAAAC0Gf2kUVLCv/AAj5IQADQGgcAAAACQGf+UQn/wALKCEAA0BoHCEAA0BoHAAAAAkBn/tEJ/8ACykhAANAaBwAAAANQZvgNExDP/6plgAMuSEAA0BoHCEAA0BoHAAAAAtBnh5FFSwr/wAI+CEAA0BoHAAAAAkBnj1EJ/8ACyghAANAaBwhAANAaBwAAAAJAZ4/RCf/AAspIQADQGgcAAAADUGaJDRMQz/+qZYADLghAANAaBwAAAALQZ5CRRUsK/8ACPkhAANAaBwhAANAaBwAAAAJAZ5hRCf/AAsoIQADQGgcAAAACQGeY0Qn/wALKSEAA0BoHCEAA0BoHAAAAA1Bmmg0TEM//qmWAAy5IQADQGgcAAAAC0GehkUVLCv/AAj5IQADQGgcIQADQGgcAAAACQGepUQn/wALKSEAA0BoHAAAAAkBnqdEJ/8ACyghAANAaBwAAAANQZqsNExDP/6plgAMuCEAA0BoHCEAA0BoHAAAAAtBnspFFSwr/wAI+SEAA0BoHAAAAAkBnulEJ/8ACyghAANAaBwhAANAaBwAAAAJAZ7rRCf/AAsoIQADQGgcAAAADUGa8DRMQz/+qZYADLkhAANAaBwhAANAaBwAAAALQZ8ORRUsK/8ACPkhAANAaBwAAAAJAZ8tRCf/AAspIQADQGgcIQADQGgcAAAACQGfL0Qn/wALKCEAA0BoHAAAAA1BmzQ0TEM//qmWAAy4IQADQGgcAAAAC0GfUkUVLCv/AAj5IQADQGgcIQADQGgcAAAACQGfcUQn/wALKCEAA0BoHAAAAAkBn3NEJ/8ACyghAANAaBwhAANAaBwAAAANQZt4NExC//6plgAMuSEAA0BoHAAAAAtBn5ZFFSwr/wAI+CEAA0BoHCEAA0BoHAAAAAkBn7VEJ/8ACykhAANAaBwAAAAJAZ+3RCf/AAspIQADQGgcAAAADUGbuzRMQn/+nhAAYsAhAANAaBwhAANAaBwAAAAJQZ/aQhP/AAspIQADQGgcAAAACQGf+UQn/wALKCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHAAACiFtb292AAAAbG12aGQAAAAA1YCCX9WAgl8AAAPoAAAH/AABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAGGlvZHMAAAAAEICAgAcAT////v7/AAAF+XRyYWsAAABcdGtoZAAAAAPVgIJf1YCCXwAAAAEAAAAAAAAH0AAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAygAAAMoAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAB9AAABdwAAEAAAAABXFtZGlhAAAAIG1kaGQAAAAA1YCCX9WAgl8AAV+QAAK/IFXEAAAAAAAtaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAFZpZGVvSGFuZGxlcgAAAAUcbWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAAE3HN0YmwAAACYc3RzZAAAAAAAAAABAAAAiGF2YzEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAygDKAEgAAABIAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY//8AAAAyYXZjQwFNQCj/4QAbZ01AKOyho3ySTUBAQFAAAAMAEAAr8gDxgxlgAQAEaO+G8gAAABhzdHRzAAAAAAAAAAEAAAA8AAALuAAAABRzdHNzAAAAAAAAAAEAAAABAAAB8GN0dHMAAAAAAAAAPAAAAAEAABdwAAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAAC7gAAAAAQAAF3AAAAABAAAAAAAAABxzdHNjAAAAAAAAAAEAAAABAAAAAQAAAAEAAAEEc3RzegAAAAAAAAAAAAAAPAAAAzQAAAAQAAAADQAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAANAAAADQAAAQBzdGNvAAAAAAAAADwAAAAwAAADZAAAA3QAAAONAAADoAAAA7kAAAPQAAAD6wAAA/4AAAQXAAAELgAABEMAAARcAAAEbwAABIwAAAShAAAEugAABM0AAATkAAAE/wAABRIAAAUrAAAFQgAABV0AAAVwAAAFiQAABaAAAAW1AAAFzgAABeEAAAX+AAAGEwAABiwAAAY/AAAGVgAABnEAAAaEAAAGnQAABrQAAAbPAAAG4gAABvUAAAcSAAAHJwAAB0AAAAdTAAAHcAAAB4UAAAeeAAAHsQAAB8gAAAfjAAAH9gAACA8AAAgmAAAIQQAACFQAAAhnAAAIhAAACJcAAAMsdHJhawAAAFx0a2hkAAAAA9WAgl/VgIJfAAAAAgAAAAAAAAf8AAAAAAAAAAAAAAABAQAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAACsm1kaWEAAAAgbWRoZAAAAADVgIJf1YCCXwAArEQAAWAAVcQAAAAAACdoZGxyAAAAAAAAAABzb3VuAAAAAAAAAAAAAAAAU3RlcmVvAAAAAmNtaW5mAAAAEHNtaGQAAAAAAAAAAAAAACRkaW5mAAAAHGRyZWYAAAAAAAAAAQAAAAx1cmwgAAAAAQAAAidzdGJsAAAAZ3N0c2QAAAAAAAAAAQAAAFdtcDRhAAAAAAAAAAEAAAAAAAAAAAACABAAAAAArEQAAAAAADNlc2RzAAAAAAOAgIAiAAIABICAgBRAFQAAAAADDUAAAAAABYCAgAISEAaAgIABAgAAABhzdHRzAAAAAAAAAAEAAABYAAAEAAAAABxzdHNjAAAAAAAAAAEAAAABAAAAAQAAAAEAAAAUc3RzegAAAAAAAAAGAAAAWAAAAXBzdGNvAAAAAAAAAFgAAAOBAAADhwAAA5oAAAOtAAADswAAA8oAAAPfAAAD5QAAA/gAAAQLAAAEEQAABCgAAAQ9AAAEUAAABFYAAARpAAAEgAAABIYAAASbAAAErgAABLQAAATHAAAE3gAABPMAAAT5AAAFDAAABR8AAAUlAAAFPAAABVEAAAVXAAAFagAABX0AAAWDAAAFmgAABa8AAAXCAAAFyAAABdsAAAXyAAAF+AAABg0AAAYgAAAGJgAABjkAAAZQAAAGZQAABmsAAAZ+AAAGkQAABpcAAAauAAAGwwAABskAAAbcAAAG7wAABwYAAAcMAAAHIQAABzQAAAc6AAAHTQAAB2QAAAdqAAAHfwAAB5IAAAeYAAAHqwAAB8IAAAfXAAAH3QAAB/AAAAgDAAAICQAACCAAAAg1AAAIOwAACE4AAAhhAAAIeAAACH4AAAiRAAAIpAAACKoAAAiwAAAItgAACLwAAAjCAAAAFnVkdGEAAAAObmFtZVN0ZXJlbwAAAHB1ZHRhAAAAaG1ldGEAAAAAAAAAIWhkbHIAAAAAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAAO2lsc3QAAAAzqXRvbwAAACtkYXRhAAAAAQAAAABIYW5kQnJha2UgMC4xMC4yIDIwMTUwNjExMDA='; + }]); + }); + }); + var NoSleep$1 = unwrapExports$$1(NoSleep); + var nextDisplayId = 1000; + var defaultLeftBounds = [0, 0, 0.5, 1]; + var defaultRightBounds = [0.5, 0, 0.5, 1]; + var raf = window.requestAnimationFrame; + var caf = window.cancelAnimationFrame; + function VRFrameData() { + this.leftProjectionMatrix = new Float32Array(16); + this.leftViewMatrix = new Float32Array(16); + this.rightProjectionMatrix = new Float32Array(16); + this.rightViewMatrix = new Float32Array(16); + this.pose = null; + } + function VRDisplayCapabilities(config) { + Object.defineProperties(this, { + hasPosition: { + writable: false, + enumerable: true, + value: config.hasPosition + }, + hasExternalDisplay: { + writable: false, + enumerable: true, + value: config.hasExternalDisplay + }, + canPresent: { + writable: false, + enumerable: true, + value: config.canPresent + }, + maxLayers: { + writable: false, + enumerable: true, + value: config.maxLayers + }, + hasOrientation: { + enumerable: true, + get: function get() { + deprecateWarning('VRDisplayCapabilities.prototype.hasOrientation', 'VRDisplay.prototype.getFrameData'); + return config.hasOrientation; + } + } + }); + } + function VRDisplay(config) { + config = config || {}; + var USE_WAKELOCK = 'wakelock' in config ? config.wakelock : true; + this.isPolyfilled = true; + this.displayId = nextDisplayId++; + this.displayName = ''; + this.depthNear = 0.01; + this.depthFar = 10000.0; + this.isPresenting = false; + Object.defineProperty(this, 'isConnected', { + get: function get() { + deprecateWarning('VRDisplay.prototype.isConnected', 'VRDisplayCapabilities.prototype.hasExternalDisplay'); + return false; + } + }); + this.capabilities = new VRDisplayCapabilities({ + hasPosition: false, + hasOrientation: false, + hasExternalDisplay: false, + canPresent: false, + maxLayers: 1 + }); + this.stageParameters = null; + this.waitingForPresent_ = false; + this.layer_ = null; + this.originalParent_ = null; + this.fullscreenElement_ = null; + this.fullscreenWrapper_ = null; + this.fullscreenElementCachedStyle_ = null; + this.fullscreenEventTarget_ = null; + this.fullscreenChangeHandler_ = null; + this.fullscreenErrorHandler_ = null; + if (USE_WAKELOCK && isMobile()) { + this.wakelock_ = new NoSleep$1(); + } + } + VRDisplay.prototype.getFrameData = function (frameData) { + return frameDataFromPose(frameData, this._getPose(), this); + }; + VRDisplay.prototype.getPose = function () { + deprecateWarning('VRDisplay.prototype.getPose', 'VRDisplay.prototype.getFrameData'); + return this._getPose(); + }; + VRDisplay.prototype.resetPose = function () { + deprecateWarning('VRDisplay.prototype.resetPose'); + return this._resetPose(); + }; + VRDisplay.prototype.getImmediatePose = function () { + deprecateWarning('VRDisplay.prototype.getImmediatePose', 'VRDisplay.prototype.getFrameData'); + return this._getPose(); + }; + VRDisplay.prototype.requestAnimationFrame = function (callback) { + return raf(callback); + }; + VRDisplay.prototype.cancelAnimationFrame = function (id) { + return caf(id); + }; + VRDisplay.prototype.wrapForFullscreen = function (element) { + if (isIOS()) { + return element; + } + if (!this.fullscreenWrapper_) { + this.fullscreenWrapper_ = document.createElement('div'); + var cssProperties = ['height: ' + Math.min(screen.height, screen.width) + 'px !important', 'top: 0 !important', 'left: 0 !important', 'right: 0 !important', 'border: 0', 'margin: 0', 'padding: 0', 'z-index: 999999 !important', 'position: fixed']; + this.fullscreenWrapper_.setAttribute('style', cssProperties.join('; ') + ';'); + this.fullscreenWrapper_.classList.add('webvr-polyfill-fullscreen-wrapper'); + } + if (this.fullscreenElement_ == element) { + return this.fullscreenWrapper_; + } + if (this.fullscreenElement_) { + if (this.originalParent_) { + this.originalParent_.appendChild(this.fullscreenElement_); + } else { + this.fullscreenElement_.parentElement.removeChild(this.fullscreenElement_); + } + } + this.fullscreenElement_ = element; + this.originalParent_ = element.parentElement; + if (!this.originalParent_) { + document.body.appendChild(element); + } + if (!this.fullscreenWrapper_.parentElement) { + var parent = this.fullscreenElement_.parentElement; + parent.insertBefore(this.fullscreenWrapper_, this.fullscreenElement_); + parent.removeChild(this.fullscreenElement_); + } + this.fullscreenWrapper_.insertBefore(this.fullscreenElement_, this.fullscreenWrapper_.firstChild); + this.fullscreenElementCachedStyle_ = this.fullscreenElement_.getAttribute('style'); + var self = this; + function applyFullscreenElementStyle() { + if (!self.fullscreenElement_) { + return; + } + var cssProperties = ['position: absolute', 'top: 0', 'left: 0', 'width: ' + Math.max(screen.width, screen.height) + 'px', 'height: ' + Math.min(screen.height, screen.width) + 'px', 'border: 0', 'margin: 0', 'padding: 0']; + self.fullscreenElement_.setAttribute('style', cssProperties.join('; ') + ';'); + } + applyFullscreenElementStyle(); + return this.fullscreenWrapper_; + }; + VRDisplay.prototype.removeFullscreenWrapper = function () { + if (!this.fullscreenElement_) { + return; + } + var element = this.fullscreenElement_; + if (this.fullscreenElementCachedStyle_) { + element.setAttribute('style', this.fullscreenElementCachedStyle_); + } else { + element.removeAttribute('style'); + } + this.fullscreenElement_ = null; + this.fullscreenElementCachedStyle_ = null; + var parent = this.fullscreenWrapper_.parentElement; + this.fullscreenWrapper_.removeChild(element); + if (this.originalParent_ === parent) { + parent.insertBefore(element, this.fullscreenWrapper_); + } else if (this.originalParent_) { + this.originalParent_.appendChild(element); + } + parent.removeChild(this.fullscreenWrapper_); + return element; + }; + VRDisplay.prototype.requestPresent = function (layers) { + var wasPresenting = this.isPresenting; + var self = this; + if (!(layers instanceof Array)) { + deprecateWarning('VRDisplay.prototype.requestPresent with non-array argument', 'an array of VRLayers as the first argument'); + layers = [layers]; + } + return new Promise(function (resolve, reject) { + if (!self.capabilities.canPresent) { + reject(new Error('VRDisplay is not capable of presenting.')); + return; + } + if (layers.length == 0 || layers.length > self.capabilities.maxLayers) { + reject(new Error('Invalid number of layers.')); + return; + } + var incomingLayer = layers[0]; + if (!incomingLayer.source) { + resolve(); + return; + } + var leftBounds = incomingLayer.leftBounds || defaultLeftBounds; + var rightBounds = incomingLayer.rightBounds || defaultRightBounds; + if (wasPresenting) { + var layer = self.layer_; + if (layer.source !== incomingLayer.source) { + layer.source = incomingLayer.source; + } + for (var i = 0; i < 4; i++) { + layer.leftBounds[i] = leftBounds[i]; + layer.rightBounds[i] = rightBounds[i]; + } + self.wrapForFullscreen(self.layer_.source); + self.updatePresent_(); + resolve(); + return; + } + self.layer_ = { + predistorted: incomingLayer.predistorted, + source: incomingLayer.source, + leftBounds: leftBounds.slice(0), + rightBounds: rightBounds.slice(0) + }; + self.waitingForPresent_ = false; + if (self.layer_ && self.layer_.source) { + var fullscreenElement = self.wrapForFullscreen(self.layer_.source); + var onFullscreenChange = function onFullscreenChange() { + var actualFullscreenElement = getFullscreenElement(); + self.isPresenting = fullscreenElement === actualFullscreenElement; + if (self.isPresenting) { + if (screen.orientation && screen.orientation.lock) { + screen.orientation.lock('landscape-primary').catch(function (error) { + console.error('screen.orientation.lock() failed due to', error.message); + }); + } + self.waitingForPresent_ = false; + self.beginPresent_(); + resolve(); + } else { + if (screen.orientation && screen.orientation.unlock) { + screen.orientation.unlock(); + } + self.removeFullscreenWrapper(); + self.disableWakeLock(); + self.endPresent_(); + self.removeFullscreenListeners_(); + } + self.fireVRDisplayPresentChange_(); + }; + var onFullscreenError = function onFullscreenError() { + if (!self.waitingForPresent_) { + return; + } + self.removeFullscreenWrapper(); + self.removeFullscreenListeners_(); + self.disableWakeLock(); + self.waitingForPresent_ = false; + self.isPresenting = false; + reject(new Error('Unable to present.')); + }; + self.addFullscreenListeners_(fullscreenElement, onFullscreenChange, onFullscreenError); + if (requestFullscreen(fullscreenElement)) { + self.enableWakeLock(); + self.waitingForPresent_ = true; + } else if (isIOS() || isWebViewAndroid()) { + self.enableWakeLock(); + self.isPresenting = true; + self.beginPresent_(); + self.fireVRDisplayPresentChange_(); + resolve(); + } + } + if (!self.waitingForPresent_ && !isIOS()) { + exitFullscreen(); + reject(new Error('Unable to present.')); + } + }); + }; + VRDisplay.prototype.exitPresent = function () { + var wasPresenting = this.isPresenting; + var self = this; + this.isPresenting = false; + this.layer_ = null; + this.disableWakeLock(); + return new Promise(function (resolve, reject) { + if (wasPresenting) { + if (!exitFullscreen() && isIOS()) { + self.endPresent_(); + self.fireVRDisplayPresentChange_(); + } + if (isWebViewAndroid()) { + self.removeFullscreenWrapper(); + self.removeFullscreenListeners_(); + self.endPresent_(); + self.fireVRDisplayPresentChange_(); + } + resolve(); + } else { + reject(new Error('Was not presenting to VRDisplay.')); + } + }); + }; + VRDisplay.prototype.getLayers = function () { + if (this.layer_) { + return [this.layer_]; + } + return []; + }; + VRDisplay.prototype.fireVRDisplayPresentChange_ = function () { + var event = new CustomEvent('vrdisplaypresentchange', { + detail: { + display: this + } + }); + window.dispatchEvent(event); + }; + VRDisplay.prototype.fireVRDisplayConnect_ = function () { + var event = new CustomEvent('vrdisplayconnect', { + detail: { + display: this + } + }); + window.dispatchEvent(event); + }; + VRDisplay.prototype.addFullscreenListeners_ = function (element, changeHandler, errorHandler) { + this.removeFullscreenListeners_(); + this.fullscreenEventTarget_ = element; + this.fullscreenChangeHandler_ = changeHandler; + this.fullscreenErrorHandler_ = errorHandler; + if (changeHandler) { + if (document.fullscreenEnabled) { + element.addEventListener('fullscreenchange', changeHandler, false); + } else if (document.webkitFullscreenEnabled) { + element.addEventListener('webkitfullscreenchange', changeHandler, false); + } else if (document.mozFullScreenEnabled) { + document.addEventListener('mozfullscreenchange', changeHandler, false); + } else if (document.msFullscreenEnabled) { + element.addEventListener('msfullscreenchange', changeHandler, false); + } + } + if (errorHandler) { + if (document.fullscreenEnabled) { + element.addEventListener('fullscreenerror', errorHandler, false); + } else if (document.webkitFullscreenEnabled) { + element.addEventListener('webkitfullscreenerror', errorHandler, false); + } else if (document.mozFullScreenEnabled) { + document.addEventListener('mozfullscreenerror', errorHandler, false); + } else if (document.msFullscreenEnabled) { + element.addEventListener('msfullscreenerror', errorHandler, false); + } + } + }; + VRDisplay.prototype.removeFullscreenListeners_ = function () { + if (!this.fullscreenEventTarget_) return; + var element = this.fullscreenEventTarget_; + if (this.fullscreenChangeHandler_) { + var changeHandler = this.fullscreenChangeHandler_; + element.removeEventListener('fullscreenchange', changeHandler, false); + element.removeEventListener('webkitfullscreenchange', changeHandler, false); + document.removeEventListener('mozfullscreenchange', changeHandler, false); + element.removeEventListener('msfullscreenchange', changeHandler, false); + } + if (this.fullscreenErrorHandler_) { + var errorHandler = this.fullscreenErrorHandler_; + element.removeEventListener('fullscreenerror', errorHandler, false); + element.removeEventListener('webkitfullscreenerror', errorHandler, false); + document.removeEventListener('mozfullscreenerror', errorHandler, false); + element.removeEventListener('msfullscreenerror', errorHandler, false); + } + this.fullscreenEventTarget_ = null; + this.fullscreenChangeHandler_ = null; + this.fullscreenErrorHandler_ = null; + }; + VRDisplay.prototype.enableWakeLock = function () { + if (this.wakelock_) { + this.wakelock_.enable(); + } + }; + VRDisplay.prototype.disableWakeLock = function () { + if (this.wakelock_) { + this.wakelock_.disable(); + } + }; + VRDisplay.prototype.beginPresent_ = function () {}; + VRDisplay.prototype.endPresent_ = function () {}; + VRDisplay.prototype.submitFrame = function (pose) {}; + VRDisplay.prototype.getEyeParameters = function (whichEye) { + return null; + }; + var config = { + ADDITIONAL_VIEWERS: [], + DEFAULT_VIEWER: '', + MOBILE_WAKE_LOCK: true, + DEBUG: false, + DPDB_URL: 'https://dpdb.webvr.rocks/dpdb.json', + K_FILTER: 0.98, + PREDICTION_TIME_S: 0.040, + CARDBOARD_UI_DISABLED: false, + ROTATE_INSTRUCTIONS_DISABLED: false, + YAW_ONLY: false, + BUFFER_SCALE: 0.5, + DIRTY_SUBMIT_FRAME_BINDINGS: false + }; + var Eye = { + LEFT: 'left', + RIGHT: 'right' + }; + function CardboardVRDisplay(config$$1) { + var defaults = extend({}, config); + config$$1 = extend(defaults, config$$1 || {}); + VRDisplay.call(this, { + wakelock: config$$1.MOBILE_WAKE_LOCK + }); + this.config = config$$1; + this.displayName = 'Cardboard VRDisplay'; + this.capabilities = new VRDisplayCapabilities({ + hasPosition: false, + hasOrientation: true, + hasExternalDisplay: false, + canPresent: true, + maxLayers: 1 + }); + this.stageParameters = null; + this.bufferScale_ = this.config.BUFFER_SCALE; + this.poseSensor_ = new PoseSensor(this.config); + this.distorter_ = null; + this.cardboardUI_ = null; + this.dpdb_ = new Dpdb(this.config.DPDB_URL, this.onDeviceParamsUpdated_.bind(this)); + this.deviceInfo_ = new DeviceInfo(this.dpdb_.getDeviceParams(), config$$1.ADDITIONAL_VIEWERS); + this.viewerSelector_ = new ViewerSelector(config$$1.DEFAULT_VIEWER); + this.viewerSelector_.onChange(this.onViewerChanged_.bind(this)); + this.deviceInfo_.setViewer(this.viewerSelector_.getCurrentViewer()); + if (!this.config.ROTATE_INSTRUCTIONS_DISABLED) { + this.rotateInstructions_ = new RotateInstructions(); + } + if (isIOS()) { + window.addEventListener('resize', this.onResize_.bind(this)); + } + } + CardboardVRDisplay.prototype = Object.create(VRDisplay.prototype); + CardboardVRDisplay.prototype._getPose = function () { + return { + position: null, + orientation: this.poseSensor_.getOrientation(), + linearVelocity: null, + linearAcceleration: null, + angularVelocity: null, + angularAcceleration: null + }; + }; + CardboardVRDisplay.prototype._resetPose = function () { + if (this.poseSensor_.resetPose) { + this.poseSensor_.resetPose(); + } + }; + CardboardVRDisplay.prototype._getFieldOfView = function (whichEye) { + var fieldOfView; + if (whichEye == Eye.LEFT) { + fieldOfView = this.deviceInfo_.getFieldOfViewLeftEye(); + } else if (whichEye == Eye.RIGHT) { + fieldOfView = this.deviceInfo_.getFieldOfViewRightEye(); + } else { + console.error('Invalid eye provided: %s', whichEye); + return null; + } + return fieldOfView; + }; + CardboardVRDisplay.prototype._getEyeOffset = function (whichEye) { + var offset; + if (whichEye == Eye.LEFT) { + offset = [-this.deviceInfo_.viewer.interLensDistance * 0.5, 0.0, 0.0]; + } else if (whichEye == Eye.RIGHT) { + offset = [this.deviceInfo_.viewer.interLensDistance * 0.5, 0.0, 0.0]; + } else { + console.error('Invalid eye provided: %s', whichEye); + return null; + } + return offset; + }; + CardboardVRDisplay.prototype.getEyeParameters = function (whichEye) { + var offset = this._getEyeOffset(whichEye); + var fieldOfView = this._getFieldOfView(whichEye); + var eyeParams = { + offset: offset, + renderWidth: this.deviceInfo_.device.width * 0.5 * this.bufferScale_, + renderHeight: this.deviceInfo_.device.height * this.bufferScale_ + }; + Object.defineProperty(eyeParams, 'fieldOfView', { + enumerable: true, + get: function get() { + deprecateWarning('VRFieldOfView', 'VRFrameData\'s projection matrices'); + return fieldOfView; + } + }); + return eyeParams; + }; + CardboardVRDisplay.prototype.onDeviceParamsUpdated_ = function (newParams) { + if (this.config.DEBUG) { + console.log('DPDB reported that device params were updated.'); + } + this.deviceInfo_.updateDeviceParams(newParams); + if (this.distorter_) { + this.distorter_.updateDeviceInfo(this.deviceInfo_); + } + }; + CardboardVRDisplay.prototype.updateBounds_ = function () { + if (this.layer_ && this.distorter_ && (this.layer_.leftBounds || this.layer_.rightBounds)) { + this.distorter_.setTextureBounds(this.layer_.leftBounds, this.layer_.rightBounds); + } + }; + CardboardVRDisplay.prototype.beginPresent_ = function () { + var gl = this.layer_.source.getContext('webgl'); + if (!gl) gl = this.layer_.source.getContext('experimental-webgl'); + if (!gl) gl = this.layer_.source.getContext('webgl2'); + if (!gl) return; + if (this.layer_.predistorted) { + if (!this.config.CARDBOARD_UI_DISABLED) { + gl.canvas.width = getScreenWidth() * this.bufferScale_; + gl.canvas.height = getScreenHeight() * this.bufferScale_; + this.cardboardUI_ = new CardboardUI(gl); + } + } else { + if (!this.config.CARDBOARD_UI_DISABLED) { + this.cardboardUI_ = new CardboardUI(gl); + } + this.distorter_ = new CardboardDistorter(gl, this.cardboardUI_, this.config.BUFFER_SCALE, this.config.DIRTY_SUBMIT_FRAME_BINDINGS); + this.distorter_.updateDeviceInfo(this.deviceInfo_); + } + if (this.cardboardUI_) { + this.cardboardUI_.listen(function (e) { + this.viewerSelector_.show(this.layer_.source.parentElement); + e.stopPropagation(); + e.preventDefault(); + }.bind(this), function (e) { + this.exitPresent(); + e.stopPropagation(); + e.preventDefault(); + }.bind(this)); + } + if (this.rotateInstructions_) { + if (isLandscapeMode() && isMobile()) { + this.rotateInstructions_.showTemporarily(3000, this.layer_.source.parentElement); + } else { + this.rotateInstructions_.update(); + } + } + this.orientationHandler = this.onOrientationChange_.bind(this); + window.addEventListener('orientationchange', this.orientationHandler); + this.vrdisplaypresentchangeHandler = this.updateBounds_.bind(this); + window.addEventListener('vrdisplaypresentchange', this.vrdisplaypresentchangeHandler); + this.fireVRDisplayDeviceParamsChange_(); + }; + CardboardVRDisplay.prototype.endPresent_ = function () { + if (this.distorter_) { + this.distorter_.destroy(); + this.distorter_ = null; + } + if (this.cardboardUI_) { + this.cardboardUI_.destroy(); + this.cardboardUI_ = null; + } + if (this.rotateInstructions_) { + this.rotateInstructions_.hide(); + } + this.viewerSelector_.hide(); + window.removeEventListener('orientationchange', this.orientationHandler); + window.removeEventListener('vrdisplaypresentchange', this.vrdisplaypresentchangeHandler); + }; + CardboardVRDisplay.prototype.updatePresent_ = function () { + this.endPresent_(); + this.beginPresent_(); + }; + CardboardVRDisplay.prototype.submitFrame = function (pose) { + if (this.distorter_) { + this.updateBounds_(); + this.distorter_.submitFrame(); + } else if (this.cardboardUI_ && this.layer_) { + var gl = this.layer_.source.getContext('webgl'); + if (!gl) gl = this.layer_.source.getContext('experimental-webgl'); + if (!gl) gl = this.layer_.source.getContext('webgl2'); + var canvas = gl.canvas; + if (canvas.width != this.lastWidth || canvas.height != this.lastHeight) { + this.cardboardUI_.onResize(); + } + this.lastWidth = canvas.width; + this.lastHeight = canvas.height; + this.cardboardUI_.render(); + } + }; + CardboardVRDisplay.prototype.onOrientationChange_ = function (e) { + this.viewerSelector_.hide(); + if (this.rotateInstructions_) { + this.rotateInstructions_.update(); + } + this.onResize_(); + }; + CardboardVRDisplay.prototype.onResize_ = function (e) { + if (this.layer_) { + var gl = this.layer_.source.getContext('webgl'); + if (!gl) gl = this.layer_.source.getContext('experimental-webgl'); + if (!gl) gl = this.layer_.source.getContext('webgl2'); + var cssProperties = ['position: absolute', 'top: 0', 'left: 0', 'width: 100vw', 'height: 100vh', 'border: 0', 'margin: 0', 'padding: 0px', 'box-sizing: content-box']; + gl.canvas.setAttribute('style', cssProperties.join('; ') + ';'); + safariCssSizeWorkaround(gl.canvas); + } + }; + CardboardVRDisplay.prototype.onViewerChanged_ = function (viewer) { + this.deviceInfo_.setViewer(viewer); + if (this.distorter_) { + this.distorter_.updateDeviceInfo(this.deviceInfo_); + } + this.fireVRDisplayDeviceParamsChange_(); + }; + CardboardVRDisplay.prototype.fireVRDisplayDeviceParamsChange_ = function () { + var event = new CustomEvent('vrdisplaydeviceparamschange', { + detail: { + vrdisplay: this, + deviceInfo: this.deviceInfo_ + } + }); + window.dispatchEvent(event); + }; + CardboardVRDisplay.VRFrameData = VRFrameData; + CardboardVRDisplay.VRDisplay = VRDisplay; + return CardboardVRDisplay; + }); + }); + var CardboardVRDisplay = unwrapExports(cardboardVrDisplay); + var version = "0.10.12"; + var DefaultConfig = { + ADDITIONAL_VIEWERS: [], + DEFAULT_VIEWER: '', + PROVIDE_MOBILE_VRDISPLAY: true, + MOBILE_WAKE_LOCK: true, + DEBUG: false, + DPDB_URL: 'https://dpdb.webvr.rocks/dpdb.json', + K_FILTER: 0.98, + PREDICTION_TIME_S: 0.040, + CARDBOARD_UI_DISABLED: false, + ROTATE_INSTRUCTIONS_DISABLED: false, + YAW_ONLY: false, + BUFFER_SCALE: 0.5, + DIRTY_SUBMIT_FRAME_BINDINGS: false + }; + function WebVRPolyfill(config) { + this.config = extend(extend({}, DefaultConfig), config); + this.polyfillDisplays = []; + this.enabled = false; + this.hasNative = 'getVRDisplays' in navigator; + this.native = {}; + this.native.getVRDisplays = navigator.getVRDisplays; + this.native.VRFrameData = window.VRFrameData; + this.native.VRDisplay = window.VRDisplay; + if (!this.hasNative || this.config.PROVIDE_MOBILE_VRDISPLAY && isMobile()) { + this.enable(); + this.getVRDisplays().then(function (displays) { + if (displays && displays[0] && displays[0].fireVRDisplayConnect_) { + displays[0].fireVRDisplayConnect_(); + } + }); + } + } + WebVRPolyfill.prototype.getPolyfillDisplays = function () { + if (this._polyfillDisplaysPopulated) { + return this.polyfillDisplays; + } + if (isMobile()) { + var vrDisplay = new CardboardVRDisplay({ + ADDITIONAL_VIEWERS: this.config.ADDITIONAL_VIEWERS, + DEFAULT_VIEWER: this.config.DEFAULT_VIEWER, + MOBILE_WAKE_LOCK: this.config.MOBILE_WAKE_LOCK, + DEBUG: this.config.DEBUG, + DPDB_URL: this.config.DPDB_URL, + CARDBOARD_UI_DISABLED: this.config.CARDBOARD_UI_DISABLED, + K_FILTER: this.config.K_FILTER, + PREDICTION_TIME_S: this.config.PREDICTION_TIME_S, + ROTATE_INSTRUCTIONS_DISABLED: this.config.ROTATE_INSTRUCTIONS_DISABLED, + YAW_ONLY: this.config.YAW_ONLY, + BUFFER_SCALE: this.config.BUFFER_SCALE, + DIRTY_SUBMIT_FRAME_BINDINGS: this.config.DIRTY_SUBMIT_FRAME_BINDINGS + }); + this.polyfillDisplays.push(vrDisplay); + } + this._polyfillDisplaysPopulated = true; + return this.polyfillDisplays; + }; + WebVRPolyfill.prototype.enable = function () { + this.enabled = true; + if (this.hasNative && this.native.VRFrameData) { + var NativeVRFrameData = this.native.VRFrameData; + var nativeFrameData = new this.native.VRFrameData(); + var nativeGetFrameData = this.native.VRDisplay.prototype.getFrameData; + window.VRDisplay.prototype.getFrameData = function (frameData) { + if (frameData instanceof NativeVRFrameData) { + nativeGetFrameData.call(this, frameData); + return; + } + nativeGetFrameData.call(this, nativeFrameData); + frameData.pose = nativeFrameData.pose; + copyArray(nativeFrameData.leftProjectionMatrix, frameData.leftProjectionMatrix); + copyArray(nativeFrameData.rightProjectionMatrix, frameData.rightProjectionMatrix); + copyArray(nativeFrameData.leftViewMatrix, frameData.leftViewMatrix); + copyArray(nativeFrameData.rightViewMatrix, frameData.rightViewMatrix); + }; + } + navigator.getVRDisplays = this.getVRDisplays.bind(this); + window.VRDisplay = CardboardVRDisplay.VRDisplay; + window.VRFrameData = CardboardVRDisplay.VRFrameData; + }; + WebVRPolyfill.prototype.getVRDisplays = function () { + var _this = this; + var config = this.config; + if (!this.hasNative) { + return Promise.resolve(this.getPolyfillDisplays()); + } + return this.native.getVRDisplays.call(navigator).then(function (nativeDisplays) { + return nativeDisplays.length > 0 ? nativeDisplays : _this.getPolyfillDisplays(); + }); + }; + WebVRPolyfill.version = version; + WebVRPolyfill.VRFrameData = CardboardVRDisplay.VRFrameData; + WebVRPolyfill.VRDisplay = CardboardVRDisplay.VRDisplay; + var webvrPolyfill = Object.freeze({ + default: WebVRPolyfill + }); + var require$$0 = webvrPolyfill && WebVRPolyfill || webvrPolyfill; + if (typeof commonjsGlobal !== 'undefined' && commonjsGlobal.window) { + if (!commonjsGlobal.document) { + commonjsGlobal.document = commonjsGlobal.window.document; + } + if (!commonjsGlobal.navigator) { + commonjsGlobal.navigator = commonjsGlobal.window.navigator; + } + } + var src = require$$0; + return src; +}); + +/***/ }), + +/***/ "./node_modules/word-wrapper/index.js": +/*!********************************************!*\ + !*** ./node_modules/word-wrapper/index.js ***! + \********************************************/ +/***/ ((module) => { + +var newline = /\n/; +var newlineChar = '\n'; +var whitespace = /\s/; +module.exports = function (text, opt) { + var lines = module.exports.lines(text, opt); + return lines.map(function (line) { + return text.substring(line.start, line.end); + }).join('\n'); +}; +module.exports.lines = function wordwrap(text, opt) { + opt = opt || {}; + + //zero width results in nothing visible + if (opt.width === 0 && opt.mode !== 'nowrap') return []; + text = text || ''; + var width = typeof opt.width === 'number' ? opt.width : Number.MAX_VALUE; + var start = Math.max(0, opt.start || 0); + var end = typeof opt.end === 'number' ? opt.end : text.length; + var mode = opt.mode; + var measure = opt.measure || monospace; + if (mode === 'pre') return pre(measure, text, start, end, width);else return greedy(measure, text, start, end, width, mode); +}; +function idxOf(text, chr, start, end) { + var idx = text.indexOf(chr, start); + if (idx === -1 || idx > end) return end; + return idx; +} +function isWhitespace(chr) { + return whitespace.test(chr); +} +function pre(measure, text, start, end, width) { + var lines = []; + var lineStart = start; + for (var i = start; i < end && i < text.length; i++) { + var chr = text.charAt(i); + var isNewline = newline.test(chr); + + //If we've reached a newline, then step down a line + //Or if we've reached the EOF + if (isNewline || i === end - 1) { + var lineEnd = isNewline ? i : i + 1; + var measured = measure(text, lineStart, lineEnd, width); + lines.push(measured); + lineStart = i + 1; + } + } + return lines; +} +function greedy(measure, text, start, end, width, mode) { + //A greedy word wrapper based on LibGDX algorithm + //https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/BitmapFontCache.java + var lines = []; + var testWidth = width; + //if 'nowrap' is specified, we only wrap on newline chars + if (mode === 'nowrap') testWidth = Number.MAX_VALUE; + while (start < end && start < text.length) { + //get next newline position + var newLine = idxOf(text, newlineChar, start, end); + + //eat whitespace at start of line + while (start < newLine) { + if (!isWhitespace(text.charAt(start))) break; + start++; + } + + //determine visible # of glyphs for the available width + var measured = measure(text, start, newLine, testWidth); + var lineEnd = start + (measured.end - measured.start); + var nextStart = lineEnd + newlineChar.length; + + //if we had to cut the line before the next newline... + if (lineEnd < newLine) { + //find char to break on + while (lineEnd > start) { + if (isWhitespace(text.charAt(lineEnd))) break; + lineEnd--; + } + if (lineEnd === start) { + if (nextStart > start + newlineChar.length) nextStart--; + lineEnd = nextStart; // If no characters to break, show all. + } else { + nextStart = lineEnd; + //eat whitespace at end of line + while (lineEnd > start) { + if (!isWhitespace(text.charAt(lineEnd - newlineChar.length))) break; + lineEnd--; + } + } + } + if (lineEnd >= start) { + var result = measure(text, start, lineEnd, testWidth); + lines.push(result); + } + start = nextStart; + } + return lines; +} + +//determines the visible number of glyphs within a given width +function monospace(text, start, end, width) { + var glyphs = Math.min(width, end - start); + return { + start: start, + end: start + glyphs + }; +} + +/***/ }), + +/***/ "./node_modules/xhr/index.js": +/*!***********************************!*\ + !*** ./node_modules/xhr/index.js ***! + \***********************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +"use strict"; + + +var window = __webpack_require__(/*! global/window */ "./node_modules/global/window.js"); +var isFunction = __webpack_require__(/*! is-function */ "./node_modules/is-function/index.js"); +var parseHeaders = __webpack_require__(/*! parse-headers */ "./node_modules/parse-headers/parse-headers.js"); +var xtend = __webpack_require__(/*! xtend */ "./node_modules/xtend/immutable.js"); +module.exports = createXHR; +// Allow use of default import syntax in TypeScript +module.exports["default"] = createXHR; +createXHR.XMLHttpRequest = window.XMLHttpRequest || noop; +createXHR.XDomainRequest = "withCredentials" in new createXHR.XMLHttpRequest() ? createXHR.XMLHttpRequest : window.XDomainRequest; +forEachArray(["get", "put", "post", "patch", "head", "delete"], function (method) { + createXHR[method === "delete" ? "del" : method] = function (uri, options, callback) { + options = initParams(uri, options, callback); + options.method = method.toUpperCase(); + return _createXHR(options); + }; +}); +function forEachArray(array, iterator) { + for (var i = 0; i < array.length; i++) { + iterator(array[i]); + } +} +function isEmpty(obj) { + for (var i in obj) { + if (obj.hasOwnProperty(i)) return false; + } + return true; +} +function initParams(uri, options, callback) { + var params = uri; + if (isFunction(options)) { + callback = options; + if (typeof uri === "string") { + params = { + uri: uri + }; + } + } else { + params = xtend(options, { + uri: uri + }); + } + params.callback = callback; + return params; +} +function createXHR(uri, options, callback) { + options = initParams(uri, options, callback); + return _createXHR(options); +} +function _createXHR(options) { + if (typeof options.callback === "undefined") { + throw new Error("callback argument missing"); + } + var called = false; + var callback = function cbOnce(err, response, body) { + if (!called) { + called = true; + options.callback(err, response, body); + } + }; + function readystatechange() { + if (xhr.readyState === 4) { + setTimeout(loadFunc, 0); + } + } + function getBody() { + // Chrome with requestType=blob throws errors arround when even testing access to responseText + var body = undefined; + if (xhr.response) { + body = xhr.response; + } else { + body = xhr.responseText || getXml(xhr); + } + if (isJson) { + try { + body = JSON.parse(body); + } catch (e) {} + } + return body; + } + function errorFunc(evt) { + clearTimeout(timeoutTimer); + if (!(evt instanceof Error)) { + evt = new Error("" + (evt || "Unknown XMLHttpRequest Error")); + } + evt.statusCode = 0; + return callback(evt, failureResponse); + } + + // will load the data & process the response in a special response object + function loadFunc() { + if (aborted) return; + var status; + clearTimeout(timeoutTimer); + if (options.useXDR && xhr.status === undefined) { + //IE8 CORS GET successful response doesn't have a status field, but body is fine + status = 200; + } else { + status = xhr.status === 1223 ? 204 : xhr.status; + } + var response = failureResponse; + var err = null; + if (status !== 0) { + response = { + body: getBody(), + statusCode: status, + method: method, + headers: {}, + url: uri, + rawRequest: xhr + }; + if (xhr.getAllResponseHeaders) { + //remember xhr can in fact be XDR for CORS in IE + response.headers = parseHeaders(xhr.getAllResponseHeaders()); + } + } else { + err = new Error("Internal XMLHttpRequest Error"); + } + return callback(err, response, response.body); + } + var xhr = options.xhr || null; + if (!xhr) { + if (options.cors || options.useXDR) { + xhr = new createXHR.XDomainRequest(); + } else { + xhr = new createXHR.XMLHttpRequest(); + } + } + var key; + var aborted; + var uri = xhr.url = options.uri || options.url; + var method = xhr.method = options.method || "GET"; + var body = options.body || options.data; + var headers = xhr.headers = options.headers || {}; + var sync = !!options.sync; + var isJson = false; + var timeoutTimer; + var failureResponse = { + body: undefined, + headers: {}, + statusCode: 0, + method: method, + url: uri, + rawRequest: xhr + }; + if ("json" in options && options.json !== false) { + isJson = true; + headers["accept"] || headers["Accept"] || (headers["Accept"] = "application/json"); //Don't override existing accept header declared by user + if (method !== "GET" && method !== "HEAD") { + headers["content-type"] || headers["Content-Type"] || (headers["Content-Type"] = "application/json"); //Don't override existing accept header declared by user + body = JSON.stringify(options.json === true ? body : options.json); + } + } + xhr.onreadystatechange = readystatechange; + xhr.onload = loadFunc; + xhr.onerror = errorFunc; + // IE9 must have onprogress be set to a unique function. + xhr.onprogress = function () { + // IE must die + }; + xhr.onabort = function () { + aborted = true; + }; + xhr.ontimeout = errorFunc; + xhr.open(method, uri, !sync, options.username, options.password); + //has to be after open + if (!sync) { + xhr.withCredentials = !!options.withCredentials; + } + // Cannot set timeout with sync request + // not setting timeout on the xhr object, because of old webkits etc. not handling that correctly + // both npm's request and jquery 1.x use this kind of timeout, so this is being consistent + if (!sync && options.timeout > 0) { + timeoutTimer = setTimeout(function () { + if (aborted) return; + aborted = true; //IE9 may still call readystatechange + xhr.abort("timeout"); + var e = new Error("XMLHttpRequest timeout"); + e.code = "ETIMEDOUT"; + errorFunc(e); + }, options.timeout); + } + if (xhr.setRequestHeader) { + for (key in headers) { + if (headers.hasOwnProperty(key)) { + xhr.setRequestHeader(key, headers[key]); + } + } + } else if (options.headers && !isEmpty(options.headers)) { + throw new Error("Headers cannot be set on an XDomainRequest object"); + } + if ("responseType" in options) { + xhr.responseType = options.responseType; + } + if ("beforeSend" in options && typeof options.beforeSend === "function") { + options.beforeSend(xhr); + } + + // Microsoft Edge browser sends "undefined" when send is called with undefined value. + // XMLHttpRequest spec says to pass null as body to indicate no body + // See https://github.com/naugtur/xhr/issues/100. + xhr.send(body || null); + return xhr; +} +function getXml(xhr) { + // xhr.responseXML will throw Exception "InvalidStateError" or "DOMException" + // See https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseXML. + try { + if (xhr.responseType === "document") { + return xhr.responseXML; + } + var firefoxBugTakenEffect = xhr.responseXML && xhr.responseXML.documentElement.nodeName === "parsererror"; + if (xhr.responseType === "" && !firefoxBugTakenEffect) { + return xhr.responseXML; + } + } catch (e) {} + return null; +} +function noop() {} + +/***/ }), + +/***/ "./node_modules/xml-parse-from-string/index.js": +/*!*****************************************************!*\ + !*** ./node_modules/xml-parse-from-string/index.js ***! + \*****************************************************/ +/***/ ((module) => { + +module.exports = function xmlparser() { + //common browsers + if (typeof self.DOMParser !== 'undefined') { + return function (str) { + var parser = new self.DOMParser(); + return parser.parseFromString(str, 'application/xml'); + }; + } + + //IE8 fallback + if (typeof self.ActiveXObject !== 'undefined' && new self.ActiveXObject('Microsoft.XMLDOM')) { + return function (str) { + var xmlDoc = new self.ActiveXObject("Microsoft.XMLDOM"); + xmlDoc.async = "false"; + xmlDoc.loadXML(str); + return xmlDoc; + }; + } + + //last resort fallback + return function (str) { + var div = document.createElement('div'); + div.innerHTML = str; + return div; + }; +}(); + +/***/ }), + +/***/ "./node_modules/xtend/immutable.js": +/*!*****************************************!*\ + !*** ./node_modules/xtend/immutable.js ***! + \*****************************************/ +/***/ ((module) => { + +module.exports = extend; +var hasOwnProperty = Object.prototype.hasOwnProperty; +function extend() { + var target = {}; + for (var i = 0; i < arguments.length; i++) { + var source = arguments[i]; + for (var key in source) { + if (hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + return target; +} + +/***/ }), + +/***/ "./src/components/animation.js": +/*!*************************************!*\ + !*** ./src/components/animation.js ***! + \*************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var anime = (__webpack_require__(/*! super-animejs */ "./node_modules/super-animejs/lib/anime.es.js")["default"]); +var components = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").components); +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var THREE = __webpack_require__(/*! ../lib/three */ "./src/lib/three.js"); +var utils = __webpack_require__(/*! ../utils */ "./src/utils/index.js"); +var colorHelperFrom = new THREE.Color(); +var colorHelperTo = new THREE.Color(); +var getComponentProperty = utils.entity.getComponentProperty; +var setComponentProperty = utils.entity.setComponentProperty; +var splitCache = {}; +var TYPE_COLOR = 'color'; +var PROP_POSITION = 'position'; +var PROP_ROTATION = 'rotation'; +var PROP_SCALE = 'scale'; +var STRING_COMPONENTS = 'components'; +var STRING_OBJECT3D = 'object3D'; + +/** + * Animation component for A-Frame using anime.js. + * + * The component manually controls the tick by setting `autoplay: false` on anime.js and + * manually * calling `animation.tick()` in the tick handler. To pause or resume, we toggle a + * boolean * flag * `isAnimationPlaying`. + * + * anime.js animation config for tweenining Javascript objects and values works as: + * + * config = { + * targets: {foo: 0.0, bar: '#000'}, + * foo: 1.0, + * bar: '#FFF' + * } + * + * The above will tween each property in `targets`. The `to` values are set in the root of + * the config. + * + * @member {object} animation - anime.js instance. + * @member {boolean} animationIsPlaying - Control if animation is playing. + */ +module.exports.Component = registerComponent('animation', { + schema: { + autoplay: { + default: true + }, + delay: { + default: 0 + }, + dir: { + default: '' + }, + dur: { + default: 1000 + }, + easing: { + default: 'easeInQuad' + }, + elasticity: { + default: 400 + }, + enabled: { + default: true + }, + from: { + default: '' + }, + loop: { + default: 0, + parse: function (value) { + // Boolean or integer. + if (value === true || value === 'true') { + return true; + } + if (value === false || value === 'false') { + return false; + } + return parseInt(value, 10); + } + }, + property: { + default: '' + }, + startEvents: { + type: 'array' + }, + pauseEvents: { + type: 'array' + }, + resumeEvents: { + type: 'array' + }, + round: { + default: false + }, + to: { + default: '' + }, + type: { + default: '' + }, + isRawProperty: { + default: false + } + }, + multiple: true, + init: function () { + var self = this; + this.eventDetail = { + name: this.attrName + }; + this.time = 0; + this.animation = null; + this.animationIsPlaying = false; + this.onStartEvent = this.onStartEvent.bind(this); + this.beginAnimation = this.beginAnimation.bind(this); + this.pauseAnimation = this.pauseAnimation.bind(this); + this.resumeAnimation = this.resumeAnimation.bind(this); + this.fromColor = {}; + this.toColor = {}; + this.targets = {}; + this.targetsArray = []; + this.updateConfigForDefault = this.updateConfigForDefault.bind(this); + this.updateConfigForRawColor = this.updateConfigForRawColor.bind(this); + this.config = { + complete: function () { + self.animationIsPlaying = false; + self.el.emit('animationcomplete', self.eventDetail, false); + if (self.id) { + self.el.emit('animationcomplete__' + self.id, self.eventDetail, false); + } + } + }; + }, + update: function (oldData) { + var config = this.config; + var data = this.data; + this.animationIsPlaying = false; + if (!this.data.enabled) { + return; + } + if (!data.property) { + return; + } + + // Base config. + config.autoplay = false; + config.direction = data.dir; + config.duration = data.dur; + config.easing = data.easing; + config.elasticity = data.elasticity; + config.loop = data.loop; + config.round = data.round; + + // Start new animation. + this.createAndStartAnimation(); + }, + tick: function (t, dt) { + if (!this.animationIsPlaying) { + return; + } + this.time += dt; + this.animation.tick(this.time); + }, + remove: function () { + this.pauseAnimation(); + this.removeEventListeners(); + }, + pause: function () { + this.paused = true; + this.pausedWasPlaying = this.animationIsPlaying; + this.pauseAnimation(); + this.removeEventListeners(); + }, + /** + * `play` handler only for resuming scene. + */ + play: function () { + if (!this.paused) { + return; + } + this.paused = false; + this.addEventListeners(); + if (this.pausedWasPlaying) { + this.resumeAnimation(); + this.pausedWasPlaying = false; + } + }, + /** + * Start animation from scratch. + */ + createAndStartAnimation: function () { + var data = this.data; + this.updateConfig(); + this.animationIsPlaying = false; + this.animation = anime(this.config); + this.animation.began = true; + this.removeEventListeners(); + this.addEventListeners(); + + // Wait for start events for animation. + if (!data.autoplay || data.startEvents && data.startEvents.length) { + return; + } + + // Delay animation. + if (data.delay) { + setTimeout(this.beginAnimation, data.delay); + return; + } + + // Play animation. + this.beginAnimation(); + }, + /** + * This is before animation start (including from startEvents). + * Set to initial state (config.from, time = 0, seekTime = 0). + */ + beginAnimation: function () { + this.updateConfig(); + this.animation.began = true; + this.time = 0; + this.animationIsPlaying = true; + this.stopRelatedAnimations(); + this.el.emit('animationbegin', this.eventDetail, false); + }, + pauseAnimation: function () { + this.animationIsPlaying = false; + }, + resumeAnimation: function () { + this.animationIsPlaying = true; + }, + /** + * startEvents callback. + */ + onStartEvent: function () { + if (!this.data.enabled) { + return; + } + this.updateConfig(); + if (this.animation) { + this.animation.pause(); + } + this.animation = anime(this.config); + + // Include the delay before each start event. + if (this.data.delay) { + setTimeout(this.beginAnimation, this.data.delay); + return; + } + this.beginAnimation(); + }, + /** + * rawProperty: true and type: color; + */ + updateConfigForRawColor: function () { + var config = this.config; + var data = this.data; + var el = this.el; + var from; + var key; + var to; + if (this.waitComponentInitRawProperty(this.updateConfigForRawColor)) { + return; + } + from = data.from === '' ? getRawProperty(el, data.property) : data.from; + to = data.to; + + // Use r/g/b vector for color type. + this.setColorConfig(from, to); + from = this.fromColor; + to = this.toColor; + this.targetsArray.length = 0; + this.targetsArray.push(from); + config.targets = this.targetsArray; + for (key in to) { + config[key] = to[key]; + } + config.update = function () { + var lastValue = {}; + return function (anim) { + var value; + value = anim.animatables[0].target; + // For animation timeline. + if (value.r === lastValue.r && value.g === lastValue.g && value.b === lastValue.b) { + return; + } + setRawProperty(el, data.property, value, data.type); + }; + }(); + }, + /** + * Stuff property into generic `property` key. + */ + updateConfigForDefault: function () { + var config = this.config; + var data = this.data; + var el = this.el; + var from; + var isBoolean; + var isNumber; + var to; + if (this.waitComponentInitRawProperty(this.updateConfigForDefault)) { + return; + } + if (data.from === '') { + // Infer from. + from = isRawProperty(data) ? getRawProperty(el, data.property) : getComponentProperty(el, data.property); + } else { + // Explicit from. + from = data.from; + } + to = data.to; + isNumber = !isNaN(from || to); + if (isNumber) { + from = parseFloat(from); + to = parseFloat(to); + } else { + from = from ? from.toString() : from; + to = to ? to.toString() : to; + } + + // Convert booleans to integer to allow boolean flipping. + isBoolean = data.to === 'true' || data.to === 'false' || data.to === true || data.to === false; + if (isBoolean) { + from = data.from === 'true' || data.from === true ? 1 : 0; + to = data.to === 'true' || data.to === true ? 1 : 0; + } + this.targets.aframeProperty = from; + config.targets = this.targets; + config.aframeProperty = to; + config.update = function () { + var lastValue; + return function (anim) { + var value; + value = anim.animatables[0].target.aframeProperty; + + // Need to do a last value check for animation timeline since all the tweening + // begins simultaenously even if the value has not changed. Also better for perf + // anyways. + if (value === lastValue) { + return; + } + lastValue = value; + if (isBoolean) { + value = value >= 1; + } + if (isRawProperty(data)) { + setRawProperty(el, data.property, value, data.type); + } else { + setComponentProperty(el, data.property, value); + } + }; + }(); + }, + /** + * Extend x/y/z/w onto the config. + * Update vector by modifying object3D. + */ + updateConfigForVector: function () { + var config = this.config; + var data = this.data; + var el = this.el; + var key; + var from; + var to; + + // Parse coordinates. + from = data.from !== '' ? utils.coordinates.parse(data.from) // If data.from defined, use that. + : getComponentProperty(el, data.property); // If data.from not defined, get on the fly. + to = utils.coordinates.parse(data.to); + if (data.property === PROP_ROTATION) { + toRadians(from); + toRadians(to); + } + + // Set to and from. + this.targetsArray.length = 0; + this.targetsArray.push(from); + config.targets = this.targetsArray; + for (key in to) { + config[key] = to[key]; + } + + // If animating object3D transformation, run more optimized updater. + if (data.property === PROP_POSITION || data.property === PROP_ROTATION || data.property === PROP_SCALE) { + config.update = function () { + var lastValue = {}; + return function (anim) { + var value = anim.animatables[0].target; + if (data.property === PROP_SCALE) { + value.x = Math.max(0.0001, value.x); + value.y = Math.max(0.0001, value.y); + value.z = Math.max(0.0001, value.z); + } + + // For animation timeline. + if (value.x === lastValue.x && value.y === lastValue.y && value.z === lastValue.z) { + return; + } + lastValue.x = value.x; + lastValue.y = value.y; + lastValue.z = value.z; + el.object3D[data.property].set(value.x, value.y, value.z); + }; + }(); + return; + } + + // Animating some vector. + config.update = function () { + var lastValue = {}; + return function (anim) { + var value = anim.animatables[0].target; + + // Animate rotation through radians. + // For animation timeline. + if (value.x === lastValue.x && value.y === lastValue.y && value.z === lastValue.z) { + return; + } + lastValue.x = value.x; + lastValue.y = value.y; + lastValue.z = value.z; + setComponentProperty(el, data.property, value); + }; + }(); + }, + /** + * Update the config before each run. + */ + updateConfig: function () { + var propType; + + // Route config type. + propType = getPropertyType(this.el, this.data.property); + if (isRawProperty(this.data) && this.data.type === TYPE_COLOR) { + this.updateConfigForRawColor(); + } else if (propType === 'vec2' || propType === 'vec3' || propType === 'vec4') { + this.updateConfigForVector(); + } else { + this.updateConfigForDefault(); + } + }, + /** + * Wait for component to initialize. + */ + waitComponentInitRawProperty: function (cb) { + var componentName; + var data = this.data; + var el = this.el; + var self = this; + if (data.from !== '') { + return false; + } + if (!data.property.startsWith(STRING_COMPONENTS)) { + return false; + } + componentName = splitDot(data.property)[1]; + if (el.components[componentName]) { + return false; + } + el.addEventListener('componentinitialized', function wait(evt) { + if (evt.detail.name !== componentName) { + return; + } + cb(); + // Since the config was created async, create the animation now since we missed it + // earlier. + self.animation = anime(self.config); + el.removeEventListener('componentinitialized', wait); + }); + return true; + }, + /** + * Make sure two animations on the same property don't fight each other. + * e.g., animation__mouseenter="property: material.opacity" + * animation__mouseleave="property: material.opacity" + */ + stopRelatedAnimations: function () { + var component; + var componentName; + for (componentName in this.el.components) { + component = this.el.components[componentName]; + if (componentName === this.attrName) { + continue; + } + if (component.name !== 'animation') { + continue; + } + if (!component.animationIsPlaying) { + continue; + } + if (component.data.property !== this.data.property) { + continue; + } + component.animationIsPlaying = false; + } + }, + addEventListeners: function () { + var data = this.data; + var el = this.el; + addEventListeners(el, data.startEvents, this.onStartEvent); + addEventListeners(el, data.pauseEvents, this.pauseAnimation); + addEventListeners(el, data.resumeEvents, this.resumeAnimation); + }, + removeEventListeners: function () { + var data = this.data; + var el = this.el; + removeEventListeners(el, data.startEvents, this.onStartEvent); + removeEventListeners(el, data.pauseEvents, this.pauseAnimation); + removeEventListeners(el, data.resumeEvents, this.resumeAnimation); + }, + setColorConfig: function (from, to) { + colorHelperFrom.set(from); + colorHelperTo.set(to); + from = this.fromColor; + to = this.toColor; + from.r = colorHelperFrom.r; + from.g = colorHelperFrom.g; + from.b = colorHelperFrom.b; + to.r = colorHelperTo.r; + to.g = colorHelperTo.g; + to.b = colorHelperTo.b; + } +}); + +/** + * Given property name, check schema to see what type we are animating. + * We just care whether the property is a vector. + */ +function getPropertyType(el, property) { + var component; + var componentName; + var split; + var propertyName; + split = property.split('.'); + componentName = split[0]; + propertyName = split[1]; + component = el.components[componentName] || components[componentName]; + + // Primitives. + if (!component) { + return null; + } + + // Dynamic schema. We only care about vectors anyways. + if (propertyName && !component.schema[propertyName]) { + return null; + } + + // Multi-prop. + if (propertyName) { + return component.schema[propertyName].type; + } + + // Single-prop. + return component.schema.type; +} + +/** + * Convert object to radians. + */ +function toRadians(obj) { + obj.x = THREE.MathUtils.degToRad(obj.x); + obj.y = THREE.MathUtils.degToRad(obj.y); + obj.z = THREE.MathUtils.degToRad(obj.z); +} +function addEventListeners(el, eventNames, handler) { + var i; + for (i = 0; i < eventNames.length; i++) { + el.addEventListener(eventNames[i], handler); + } +} +function removeEventListeners(el, eventNames, handler) { + var i; + for (i = 0; i < eventNames.length; i++) { + el.removeEventListener(eventNames[i], handler); + } +} +function getRawProperty(el, path) { + var i; + var split; + var value; + split = splitDot(path); + value = el; + for (i = 0; i < split.length; i++) { + value = value[split[i]]; + } + if (value === undefined) { + console.log(el); + throw new Error('[animation] property (' + path + ') could not be found'); + } + return value; +} +function setRawProperty(el, path, value, type) { + var i; + var split; + var propertyName; + var targetValue; + if (path.startsWith('object3D.rotation')) { + value = THREE.MathUtils.degToRad(value); + } + + // Walk. + split = splitDot(path); + targetValue = el; + for (i = 0; i < split.length - 1; i++) { + targetValue = targetValue[split[i]]; + } + propertyName = split[split.length - 1]; + + // Raw color. + if (type === TYPE_COLOR) { + if ('r' in targetValue[propertyName]) { + targetValue[propertyName].r = value.r; + targetValue[propertyName].g = value.g; + targetValue[propertyName].b = value.b; + } else { + targetValue[propertyName].x = value.r; + targetValue[propertyName].y = value.g; + targetValue[propertyName].z = value.b; + } + return; + } + targetValue[propertyName] = value; +} +function splitDot(path) { + if (path in splitCache) { + return splitCache[path]; + } + splitCache[path] = path.split('.'); + return splitCache[path]; +} +function isRawProperty(data) { + return data.isRawProperty || data.property.startsWith(STRING_COMPONENTS) || data.property.startsWith(STRING_OBJECT3D); +} + +/***/ }), + +/***/ "./src/components/camera.js": +/*!**********************************!*\ + !*** ./src/components/camera.js ***! + \**********************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var THREE = __webpack_require__(/*! ../lib/three */ "./src/lib/three.js"); + +/** + * Camera component. + * Pairs along with camera system to handle tracking the active camera. + */ +module.exports.Component = registerComponent('camera', { + schema: { + active: { + default: true + }, + far: { + default: 10000 + }, + fov: { + default: 80, + min: 0 + }, + near: { + default: 0.005, + min: 0 + }, + spectator: { + default: false + }, + zoom: { + default: 1, + min: 0 + } + }, + /** + * Initialize three.js camera and add it to the entity. + * Add reference from scene to this entity as the camera. + */ + init: function () { + var camera; + var el = this.el; + + // Create camera. + camera = this.camera = new THREE.PerspectiveCamera(); + el.setObject3D('camera', camera); + }, + /** + * Update three.js camera. + */ + update: function (oldData) { + var data = this.data; + var camera = this.camera; + + // Update properties. + camera.aspect = data.aspect || window.innerWidth / window.innerHeight; + camera.far = data.far; + camera.fov = data.fov; + camera.near = data.near; + camera.zoom = data.zoom; + camera.updateProjectionMatrix(); + this.updateActiveCamera(oldData); + this.updateSpectatorCamera(oldData); + }, + updateActiveCamera: function (oldData) { + var data = this.data; + var el = this.el; + var system = this.system; + // Active property did not change. + if (oldData && oldData.active === data.active || data.spectator) { + return; + } + + // If `active` property changes, or first update, handle active camera with system. + if (data.active && system.activeCameraEl !== el) { + // Camera enabled. Set camera to this camera. + system.setActiveCamera(el); + } else if (!data.active && system.activeCameraEl === el) { + // Camera disabled. Set camera to another camera. + system.disableActiveCamera(); + } + }, + updateSpectatorCamera: function (oldData) { + var data = this.data; + var el = this.el; + var system = this.system; + // spectator property did not change. + if (oldData && oldData.spectator === data.spectator) { + return; + } + + // If `spectator` property changes, or first update, handle spectator camera with system. + if (data.spectator && system.spectatorCameraEl !== el) { + // Camera enabled. Set camera to this camera. + system.setSpectatorCamera(el); + } else if (!data.spectator && system.spectatorCameraEl === el) { + // Camera disabled. Set camera to another camera. + system.disableSpectatorCamera(); + } + }, + /** + * Remove camera on remove (callback). + */ + remove: function () { + this.el.removeObject3D('camera'); + } +}); + +/***/ }), + +/***/ "./src/components/cursor.js": +/*!**********************************!*\ + !*** ./src/components/cursor.js ***! + \**********************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/* global THREE, MouseEvent, TouchEvent */ +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var utils = __webpack_require__(/*! ../utils/ */ "./src/utils/index.js"); +var bind = utils.bind; +var EVENTS = { + CLICK: 'click', + FUSING: 'fusing', + MOUSEENTER: 'mouseenter', + MOUSEDOWN: 'mousedown', + MOUSELEAVE: 'mouseleave', + MOUSEUP: 'mouseup' +}; +var STATES = { + FUSING: 'cursor-fusing', + HOVERING: 'cursor-hovering', + HOVERED: 'cursor-hovered' +}; +var CANVAS_EVENTS = { + DOWN: ['mousedown', 'touchstart'], + UP: ['mouseup', 'touchend'] +}; +var WEBXR_EVENTS = { + DOWN: ['selectstart'], + UP: ['selectend'] +}; +var CANVAS_HOVER_CLASS = 'a-mouse-cursor-hover'; + +/** + * Cursor component. Applies the raycaster component specifically for starting the raycaster + * from the camera and pointing from camera's facing direction, and then only returning the + * closest intersection. Cursor can be fine-tuned by setting raycaster properties. + * + * @member {object} fuseTimeout - Timeout to trigger fuse-click. + * @member {Element} cursorDownEl - Entity that was last mousedowned during current click. + * @member {object} intersection - Attributes of the current intersection event, including + * 3D- and 2D-space coordinates. See: http://threejs.org/docs/api/core/Raycaster.html + * @member {Element} intersectedEl - Currently-intersected entity. Used to keep track to + * emit events when unintersecting. + */ +module.exports.Component = registerComponent('cursor', { + dependencies: ['raycaster'], + schema: { + downEvents: { + default: [] + }, + fuse: { + default: utils.device.isMobile() + }, + fuseTimeout: { + default: 1500, + min: 0 + }, + mouseCursorStylesEnabled: { + default: true + }, + upEvents: { + default: [] + }, + rayOrigin: { + default: 'entity', + oneOf: ['mouse', 'entity', 'xrselect'] + } + }, + multiple: true, + init: function () { + var self = this; + this.fuseTimeout = undefined; + this.cursorDownEl = null; + this.intersectedEl = null; + this.canvasBounds = document.body.getBoundingClientRect(); + this.isCursorDown = false; + this.activeXRInput = null; + + // Debounce. + this.updateCanvasBounds = utils.debounce(function updateCanvasBounds() { + self.canvasBounds = self.el.sceneEl.canvas.getBoundingClientRect(); + }, 500); + this.eventDetail = {}; + this.intersectedEventDetail = { + cursorEl: this.el + }; + + // Bind methods. + this.onCursorDown = bind(this.onCursorDown, this); + this.onCursorUp = bind(this.onCursorUp, this); + this.onIntersection = bind(this.onIntersection, this); + this.onIntersectionCleared = bind(this.onIntersectionCleared, this); + this.onMouseMove = bind(this.onMouseMove, this); + this.onEnterVR = bind(this.onEnterVR, this); + }, + update: function (oldData) { + if (this.data.rayOrigin === oldData.rayOrigin) { + return; + } + this.updateMouseEventListeners(); + }, + tick: function () { + // Update on frame to allow someone to select and mousemove + var frame = this.el.sceneEl.frame; + var inputSource = this.activeXRInput; + if (this.data.rayOrigin === 'xrselect' && frame && inputSource) { + this.onMouseMove({ + frame: frame, + inputSource: inputSource, + type: 'fakeselectevent' + }); + } + }, + play: function () { + this.addEventListeners(); + }, + pause: function () { + this.removeEventListeners(); + }, + remove: function () { + var el = this.el; + el.removeState(STATES.HOVERING); + el.removeState(STATES.FUSING); + clearTimeout(this.fuseTimeout); + if (this.intersectedEl) { + this.intersectedEl.removeState(STATES.HOVERED); + } + this.removeEventListeners(); + }, + addEventListeners: function () { + var canvas; + var data = this.data; + var el = this.el; + var self = this; + function addCanvasListeners() { + canvas = el.sceneEl.canvas; + if (data.downEvents.length || data.upEvents.length) { + return; + } + CANVAS_EVENTS.DOWN.forEach(function (downEvent) { + canvas.addEventListener(downEvent, self.onCursorDown); + }); + CANVAS_EVENTS.UP.forEach(function (upEvent) { + canvas.addEventListener(upEvent, self.onCursorUp); + }); + } + canvas = el.sceneEl.canvas; + if (canvas) { + addCanvasListeners(); + } else { + el.sceneEl.addEventListener('render-target-loaded', addCanvasListeners); + } + data.downEvents.forEach(function (downEvent) { + el.addEventListener(downEvent, self.onCursorDown); + }); + data.upEvents.forEach(function (upEvent) { + el.addEventListener(upEvent, self.onCursorUp); + }); + el.addEventListener('raycaster-intersection', this.onIntersection); + el.addEventListener('raycaster-closest-entity-changed', this.onIntersection); + el.addEventListener('raycaster-intersection-cleared', this.onIntersectionCleared); + el.sceneEl.addEventListener('rendererresize', this.updateCanvasBounds); + el.sceneEl.addEventListener('enter-vr', this.onEnterVR); + window.addEventListener('resize', this.updateCanvasBounds); + window.addEventListener('scroll', this.updateCanvasBounds); + this.updateMouseEventListeners(); + }, + removeEventListeners: function () { + var canvas; + var data = this.data; + var el = this.el; + var self = this; + canvas = el.sceneEl.canvas; + if (canvas && !data.downEvents.length && !data.upEvents.length) { + CANVAS_EVENTS.DOWN.forEach(function (downEvent) { + canvas.removeEventListener(downEvent, self.onCursorDown); + }); + CANVAS_EVENTS.UP.forEach(function (upEvent) { + canvas.removeEventListener(upEvent, self.onCursorUp); + }); + } + data.downEvents.forEach(function (downEvent) { + el.removeEventListener(downEvent, self.onCursorDown); + }); + data.upEvents.forEach(function (upEvent) { + el.removeEventListener(upEvent, self.onCursorUp); + }); + el.removeEventListener('raycaster-intersection', this.onIntersection); + el.removeEventListener('raycaster-intersection-cleared', this.onIntersectionCleared); + canvas.removeEventListener('mousemove', this.onMouseMove); + canvas.removeEventListener('touchstart', this.onMouseMove); + canvas.removeEventListener('touchmove', this.onMouseMove); + el.sceneEl.removeEventListener('rendererresize', this.updateCanvasBounds); + el.sceneEl.removeEventListener('enter-vr', this.onEnterVR); + window.removeEventListener('resize', this.updateCanvasBounds); + window.removeEventListener('scroll', this.updateCanvasBounds); + }, + updateMouseEventListeners: function () { + var canvas; + var el = this.el; + canvas = el.sceneEl.canvas; + canvas.removeEventListener('mousemove', this.onMouseMove); + canvas.removeEventListener('touchmove', this.onMouseMove); + el.setAttribute('raycaster', 'useWorldCoordinates', false); + if (this.data.rayOrigin !== 'mouse') { + return; + } + canvas.addEventListener('mousemove', this.onMouseMove, false); + canvas.addEventListener('touchmove', this.onMouseMove, false); + el.setAttribute('raycaster', 'useWorldCoordinates', true); + this.updateCanvasBounds(); + }, + onMouseMove: function () { + var direction = new THREE.Vector3(); + var mouse = new THREE.Vector2(); + var origin = new THREE.Vector3(); + var rayCasterConfig = { + origin: origin, + direction: direction + }; + return function (evt) { + var bounds = this.canvasBounds; + var camera = this.el.sceneEl.camera; + var left; + var point; + var top; + var frame; + var inputSource; + var referenceSpace; + var pose; + var transform; + camera.parent.updateMatrixWorld(); + + // Calculate mouse position based on the canvas element + if (evt.type === 'touchmove' || evt.type === 'touchstart') { + // Track the first touch for simplicity. + point = evt.touches.item(0); + } else { + point = evt; + } + left = point.clientX - bounds.left; + top = point.clientY - bounds.top; + mouse.x = left / bounds.width * 2 - 1; + mouse.y = -(top / bounds.height) * 2 + 1; + if (this.data.rayOrigin === 'xrselect' && (evt.type === 'selectstart' || evt.type === 'fakeselectevent')) { + frame = evt.frame; + inputSource = evt.inputSource; + referenceSpace = this.el.renderer.xr.getReferenceSpace(); + pose = frame.getPose(inputSource.targetRaySpace, referenceSpace); + transform = pose.transform; + direction.set(0, 0, -1); + direction.applyQuaternion(transform.orientation); + origin.copy(transform.position); + } else if (evt.type === 'fakeselectout') { + direction.set(0, 1, 0); + origin.set(0, 9999, 0); + } else if (camera && camera.isPerspectiveCamera) { + origin.setFromMatrixPosition(camera.matrixWorld); + direction.set(mouse.x, mouse.y, 0.5).unproject(camera).sub(origin).normalize(); + } else if (camera && camera.isOrthographicCamera) { + origin.set(mouse.x, mouse.y, (camera.near + camera.far) / (camera.near - camera.far)).unproject(camera); // set origin in plane of camera + direction.set(0, 0, -1).transformDirection(camera.matrixWorld); + } else { + console.error('AFRAME.Raycaster: Unsupported camera type: ' + camera.type); + } + this.el.setAttribute('raycaster', rayCasterConfig); + if (evt.type === 'touchmove') { + evt.preventDefault(); + } + }; + }(), + /** + * Trigger mousedown and keep track of the mousedowned entity. + */ + onCursorDown: function (evt) { + this.isCursorDown = true; + // Raycast again for touch. + if (this.data.rayOrigin === 'mouse' && evt.type === 'touchstart') { + this.onMouseMove(evt); + this.el.components.raycaster.checkIntersections(); + evt.preventDefault(); + } + if (this.data.rayOrigin === 'xrselect' && evt.type === 'selectstart') { + this.activeXRInput = evt.inputSource; + this.onMouseMove(evt); + this.el.components.raycaster.checkIntersections(); + + // if something was tapped on don't do ar-hit-test things + if (this.el.components.raycaster.intersectedEls.length && this.el.sceneEl.components['ar-hit-test'] !== undefined && this.el.sceneEl.getAttribute('ar-hit-test').enabled) { + // Cancel the ar-hit-test behaviours and disable the ar-hit-test + this.el.sceneEl.setAttribute('ar-hit-test', 'enabled', false); + this.reenableARHitTest = true; + } + } + this.twoWayEmit(EVENTS.MOUSEDOWN, evt); + this.cursorDownEl = this.intersectedEl; + }, + /** + * Trigger mouseup if: + * - Not fusing (mobile has no mouse). + * - Currently intersecting an entity. + * - Currently-intersected entity is the same as the one when mousedown was triggered, + * in case user mousedowned one entity, dragged to another, and mouseupped. + */ + onCursorUp: function (evt) { + if (!this.isCursorDown) { + return; + } + this.isCursorDown = false; + var data = this.data; + this.twoWayEmit(EVENTS.MOUSEUP, evt); + if (this.reenableARHitTest === true) { + this.el.sceneEl.setAttribute('ar-hit-test', 'enabled', true); + this.reenableARHitTest = undefined; + } + + // If intersected entity has changed since the cursorDown, still emit mouseUp on the + // previously cursorUp entity. + if (this.cursorDownEl && this.cursorDownEl !== this.intersectedEl) { + this.intersectedEventDetail.intersection = null; + this.cursorDownEl.emit(EVENTS.MOUSEUP, this.intersectedEventDetail); + } + if ((!data.fuse || data.rayOrigin === 'mouse' || data.rayOrigin === 'xrselect') && this.intersectedEl && this.cursorDownEl === this.intersectedEl) { + this.twoWayEmit(EVENTS.CLICK, evt); + } + + // if the current xr input stops selecting then make the ray caster point somewhere else + if (data.rayOrigin === 'xrselect' && this.activeXRInput === evt.inputSource) { + this.onMouseMove({ + type: 'fakeselectout' + }); + } + this.activeXRInput = null; + this.cursorDownEl = null; + if (evt.type === 'touchend') { + evt.preventDefault(); + } + }, + /** + * Handle intersection. + */ + onIntersection: function (evt) { + var currentIntersection; + var cursorEl = this.el; + var index; + var intersectedEl; + var intersection; + + // Select closest object, excluding the cursor. + index = evt.detail.els[0] === cursorEl ? 1 : 0; + intersection = evt.detail.intersections[index]; + intersectedEl = evt.detail.els[index]; + + // If cursor is the only intersected object, ignore the event. + if (!intersectedEl) { + return; + } + + // Already intersecting this entity. + if (this.intersectedEl === intersectedEl) { + return; + } + + // Ignore events further away than active intersection. + if (this.intersectedEl) { + currentIntersection = this.el.components.raycaster.getIntersection(this.intersectedEl); + if (currentIntersection && currentIntersection.distance <= intersection.distance) { + return; + } + } + + // Unset current intersection. + this.clearCurrentIntersection(true); + this.setIntersection(intersectedEl, intersection); + }, + /** + * Handle intersection cleared. + */ + onIntersectionCleared: function (evt) { + var clearedEls = evt.detail.clearedEls; + // Check if the current intersection has ended + if (clearedEls.indexOf(this.intersectedEl) === -1) { + return; + } + this.clearCurrentIntersection(); + }, + onEnterVR: function () { + this.clearCurrentIntersection(true); + var xrSession = this.el.sceneEl.xrSession; + var self = this; + if (!xrSession) { + return; + } + if (this.data.rayOrigin === 'mouse') { + return; + } + WEBXR_EVENTS.DOWN.forEach(function (downEvent) { + xrSession.addEventListener(downEvent, self.onCursorDown); + }); + WEBXR_EVENTS.UP.forEach(function (upEvent) { + xrSession.addEventListener(upEvent, self.onCursorUp); + }); + }, + setIntersection: function (intersectedEl, intersection) { + var cursorEl = this.el; + var data = this.data; + var self = this; + + // Already intersecting. + if (this.intersectedEl === intersectedEl) { + return; + } + + // Set new intersection. + this.intersectedEl = intersectedEl; + + // Hovering. + cursorEl.addState(STATES.HOVERING); + intersectedEl.addState(STATES.HOVERED); + this.twoWayEmit(EVENTS.MOUSEENTER); + if (this.data.mouseCursorStylesEnabled && this.data.rayOrigin === 'mouse') { + this.el.sceneEl.canvas.classList.add(CANVAS_HOVER_CLASS); + } + + // Begin fuse if necessary. + if (data.fuseTimeout === 0 || !data.fuse || data.rayOrigin === 'xrselect' || data.rayOrigin === 'mouse') { + return; + } + cursorEl.addState(STATES.FUSING); + this.twoWayEmit(EVENTS.FUSING); + this.fuseTimeout = setTimeout(function fuse() { + cursorEl.removeState(STATES.FUSING); + self.twoWayEmit(EVENTS.CLICK); + }, data.fuseTimeout); + }, + clearCurrentIntersection: function (ignoreRemaining) { + var index; + var intersection; + var intersections; + var cursorEl = this.el; + + // Nothing to be cleared. + if (!this.intersectedEl) { + return; + } + + // No longer hovering (or fusing). + this.intersectedEl.removeState(STATES.HOVERED); + cursorEl.removeState(STATES.HOVERING); + cursorEl.removeState(STATES.FUSING); + this.twoWayEmit(EVENTS.MOUSELEAVE); + if (this.data.mouseCursorStylesEnabled && this.data.rayOrigin === 'mouse') { + this.el.sceneEl.canvas.classList.remove(CANVAS_HOVER_CLASS); + } + + // Unset intersected entity (after emitting the event). + this.intersectedEl = null; + + // Clear fuseTimeout. + clearTimeout(this.fuseTimeout); + + // Set intersection to another raycasted element if any. + if (ignoreRemaining === true) { + return; + } + intersections = this.el.components.raycaster.intersections; + if (intersections.length === 0) { + return; + } + // Exclude the cursor. + index = intersections[0].object.el === cursorEl ? 1 : 0; + intersection = intersections[index]; + if (!intersection) { + return; + } + this.setIntersection(intersection.object.el, intersection); + }, + /** + * Helper to emit on both the cursor and the intersected entity (if exists). + */ + twoWayEmit: function (evtName, originalEvent) { + var el = this.el; + var intersectedEl = this.intersectedEl; + var intersection; + function addOriginalEvent(detail, evt) { + if (originalEvent instanceof MouseEvent) { + detail.mouseEvent = originalEvent; + } else if (typeof TouchEvent !== 'undefined' && originalEvent instanceof TouchEvent) { + detail.touchEvent = originalEvent; + } + } + intersection = this.el.components.raycaster.getIntersection(intersectedEl); + this.eventDetail.intersectedEl = intersectedEl; + this.eventDetail.intersection = intersection; + addOriginalEvent(this.eventDetail, originalEvent); + el.emit(evtName, this.eventDetail); + if (!intersectedEl) { + return; + } + this.intersectedEventDetail.intersection = intersection; + addOriginalEvent(this.intersectedEventDetail, originalEvent); + intersectedEl.emit(evtName, this.intersectedEventDetail); + } +}); + +/***/ }), + +/***/ "./src/components/daydream-controls.js": +/*!*********************************************!*\ + !*** ./src/components/daydream-controls.js ***! + \*********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var bind = __webpack_require__(/*! ../utils/bind */ "./src/utils/bind.js"); +var trackedControlsUtils = __webpack_require__(/*! ../utils/tracked-controls */ "./src/utils/tracked-controls.js"); +var checkControllerPresentAndSetup = trackedControlsUtils.checkControllerPresentAndSetup; +var emitIfAxesChanged = trackedControlsUtils.emitIfAxesChanged; +var onButtonEvent = trackedControlsUtils.onButtonEvent; +var DAYDREAM_CONTROLLER_MODEL_BASE_URL = 'https://cdn.aframe.io/controllers/google/'; +var DAYDREAM_CONTROLLER_MODEL_OBJ_URL = DAYDREAM_CONTROLLER_MODEL_BASE_URL + 'vr_controller_daydream.obj'; +var DAYDREAM_CONTROLLER_MODEL_OBJ_MTL = DAYDREAM_CONTROLLER_MODEL_BASE_URL + 'vr_controller_daydream.mtl'; +var isWebXRAvailable = (__webpack_require__(/*! ../utils/ */ "./src/utils/index.js").device.isWebXRAvailable); +var GAMEPAD_ID_WEBXR = 'google-daydream'; +var GAMEPAD_ID_WEBVR = 'Daydream Controller'; +var GAMEPAD_ID_PREFIX = isWebXRAvailable ? GAMEPAD_ID_WEBXR : GAMEPAD_ID_WEBVR; + +/** + * Button indices: + * 0 - trackpad + * 1 - menu (never dispatched on this layer) + * 2 - system (never dispatched on this layer) + * + * Axis: + * 0 - trackpad x + * 1 - trackpad y + */ +var INPUT_MAPPING_WEBVR = { + axes: { + trackpad: [0, 1] + }, + buttons: ['trackpad', 'menu', 'system'] +}; + +/** + * Button indices: + * 0 - none + * 1 - none + * 2 - touchpad + * + * Axis: + * 0 - touchpad x + * 1 - touchpad y + * Reference: https://github.com/immersive-web/webxr-input-profiles/blob/master/packages/registry/profiles/google/google-daydream.json + */ +var INPUT_MAPPING_WEBXR = { + axes: { + touchpad: [0, 1] + }, + buttons: ['none', 'none', 'touchpad', 'menu', 'system'] +}; +var INPUT_MAPPING = isWebXRAvailable ? INPUT_MAPPING_WEBXR : INPUT_MAPPING_WEBVR; + +/** + * Daydream controls. + * Interface with Daydream controller and map Gamepad events to + * controller buttons: trackpad, menu, system + * Load a controller model and highlight the pressed buttons. + */ +module.exports.Component = registerComponent('daydream-controls', { + schema: { + hand: { + default: '' + }, + // This informs the degenerate arm model. + buttonColor: { + type: 'color', + default: '#000000' + }, + buttonTouchedColor: { + type: 'color', + default: '#777777' + }, + buttonHighlightColor: { + type: 'color', + default: '#FFFFFF' + }, + model: { + default: true + }, + orientationOffset: { + type: 'vec3' + }, + armModel: { + default: true + } + }, + mapping: INPUT_MAPPING, + bindMethods: function () { + this.onModelLoaded = bind(this.onModelLoaded, this); + this.onControllersUpdate = bind(this.onControllersUpdate, this); + this.checkIfControllerPresent = bind(this.checkIfControllerPresent, this); + this.removeControllersUpdateListener = bind(this.removeControllersUpdateListener, this); + this.onAxisMoved = bind(this.onAxisMoved, this); + }, + init: function () { + var self = this; + this.onButtonChanged = bind(this.onButtonChanged, this); + this.onButtonDown = function (evt) { + onButtonEvent(evt.detail.id, 'down', self); + }; + this.onButtonUp = function (evt) { + onButtonEvent(evt.detail.id, 'up', self); + }; + this.onButtonTouchStart = function (evt) { + onButtonEvent(evt.detail.id, 'touchstart', self); + }; + this.onButtonTouchEnd = function (evt) { + onButtonEvent(evt.detail.id, 'touchend', self); + }; + this.controllerPresent = false; + this.lastControllerCheck = 0; + this.bindMethods(); + }, + addEventListeners: function () { + var el = this.el; + el.addEventListener('buttonchanged', this.onButtonChanged); + el.addEventListener('buttondown', this.onButtonDown); + el.addEventListener('buttonup', this.onButtonUp); + el.addEventListener('touchstart', this.onButtonTouchStart); + el.addEventListener('touchend', this.onButtonTouchEnd); + el.addEventListener('model-loaded', this.onModelLoaded); + el.addEventListener('axismove', this.onAxisMoved); + this.controllerEventsActive = true; + }, + removeEventListeners: function () { + var el = this.el; + el.removeEventListener('buttonchanged', this.onButtonChanged); + el.removeEventListener('buttondown', this.onButtonDown); + el.removeEventListener('buttonup', this.onButtonUp); + el.removeEventListener('touchstart', this.onButtonTouchStart); + el.removeEventListener('touchend', this.onButtonTouchEnd); + el.removeEventListener('model-loaded', this.onModelLoaded); + el.removeEventListener('axismove', this.onAxisMoved); + this.controllerEventsActive = false; + }, + checkIfControllerPresent: function () { + checkControllerPresentAndSetup(this, GAMEPAD_ID_PREFIX, this.data.hand ? { + hand: this.data.hand + } : {}); + }, + play: function () { + this.checkIfControllerPresent(); + this.addControllersUpdateListener(); + }, + pause: function () { + this.removeEventListeners(); + this.removeControllersUpdateListener(); + }, + injectTrackedControls: function () { + var el = this.el; + var data = this.data; + el.setAttribute('tracked-controls', { + armModel: data.armModel, + hand: data.hand, + idPrefix: GAMEPAD_ID_PREFIX, + id: GAMEPAD_ID_PREFIX, + orientationOffset: data.orientationOffset + }); + if (!this.data.model) { + return; + } + this.el.setAttribute('obj-model', { + obj: DAYDREAM_CONTROLLER_MODEL_OBJ_URL, + mtl: DAYDREAM_CONTROLLER_MODEL_OBJ_MTL + }); + }, + addControllersUpdateListener: function () { + this.el.sceneEl.addEventListener('controllersupdated', this.onControllersUpdate, false); + }, + removeControllersUpdateListener: function () { + this.el.sceneEl.removeEventListener('controllersupdated', this.onControllersUpdate, false); + }, + onControllersUpdate: function () { + this.checkIfControllerPresent(); + }, + onModelLoaded: function (evt) { + var controllerObject3D = evt.detail.model; + var buttonMeshes; + if (!this.data.model) { + return; + } + buttonMeshes = this.buttonMeshes = {}; + buttonMeshes.menu = controllerObject3D.getObjectByName('AppButton_AppButton_Cylinder.004'); + buttonMeshes.system = controllerObject3D.getObjectByName('HomeButton_HomeButton_Cylinder.005'); + buttonMeshes.trackpad = controllerObject3D.getObjectByName('TouchPad_TouchPad_Cylinder.003'); + buttonMeshes.touchpad = controllerObject3D.getObjectByName('TouchPad_TouchPad_Cylinder.003'); + // Offset pivot point. + controllerObject3D.position.set(0, 0, -0.04); + }, + onAxisMoved: function (evt) { + emitIfAxesChanged(this, this.mapping.axes, evt); + }, + onButtonChanged: function (evt) { + var button = this.mapping.buttons[evt.detail.id]; + if (!button) return; + // Pass along changed event with button state, using button mapping for convenience. + this.el.emit(button + 'changed', evt.detail.state); + }, + updateModel: function (buttonName, evtName) { + if (!this.data.model) { + return; + } + this.updateButtonModel(buttonName, evtName); + }, + updateButtonModel: function (buttonName, state) { + var buttonMeshes = this.buttonMeshes; + if (!buttonMeshes || !buttonMeshes[buttonName]) { + return; + } + var color; + switch (state) { + case 'down': + color = this.data.buttonHighlightColor; + break; + case 'touchstart': + color = this.data.buttonTouchedColor; + break; + default: + color = this.data.buttonColor; + } + buttonMeshes[buttonName].material.color.set(color); + } +}); + +/***/ }), + +/***/ "./src/components/gearvr-controls.js": +/*!*******************************************!*\ + !*** ./src/components/gearvr-controls.js ***! + \*******************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var bind = __webpack_require__(/*! ../utils/bind */ "./src/utils/bind.js"); +var trackedControlsUtils = __webpack_require__(/*! ../utils/tracked-controls */ "./src/utils/tracked-controls.js"); +var checkControllerPresentAndSetup = trackedControlsUtils.checkControllerPresentAndSetup; +var emitIfAxesChanged = trackedControlsUtils.emitIfAxesChanged; +var onButtonEvent = trackedControlsUtils.onButtonEvent; +var isWebXRAvailable = (__webpack_require__(/*! ../utils/ */ "./src/utils/index.js").device.isWebXRAvailable); +var GEARVR_CONTROLLER_MODEL_BASE_URL = 'https://cdn.aframe.io/controllers/samsung/'; +var GEARVR_CONTROLLER_MODEL_OBJ_URL = GEARVR_CONTROLLER_MODEL_BASE_URL + 'gear_vr_controller.obj'; +var GEARVR_CONTROLLER_MODEL_OBJ_MTL = GEARVR_CONTROLLER_MODEL_BASE_URL + 'gear_vr_controller.mtl'; +var GAMEPAD_ID_WEBXR = 'samsung-gearvr'; +var GAMEPAD_ID_WEBVR = 'Gear VR'; + +// Prefix for Gen1 and Gen2 Oculus Touch Controllers. +var GAMEPAD_ID_PREFIX = isWebXRAvailable ? GAMEPAD_ID_WEBXR : GAMEPAD_ID_WEBVR; + +/** + * Button indices: + * 0 - trackpad + * 1 - trigger + * + * Axis: + * 0 - trackpad x + * 1 - trackpad y + */ +var INPUT_MAPPING_WEBVR = { + axes: { + trackpad: [0, 1] + }, + buttons: ['trackpad', 'trigger'] +}; + +/** + * Button indices: + * 0 - trigger + * 1 - none + * 2 - touchpad + * 3 - menu + * + * Axis: + * 0 - touchpad x + * 1 - touchpad y + * Reference: https://github.com/immersive-web/webxr-input-profiles/blob/master/packages/registry/profiles/samsung/samsung-gearvr.json + */ +var INPUT_MAPPING_WEBXR = { + axes: { + touchpad: [0, 1] + }, + buttons: ['trigger', 'none', 'touchpad', 'none', 'menu'] +}; +var INPUT_MAPPING = isWebXRAvailable ? INPUT_MAPPING_WEBXR : INPUT_MAPPING_WEBVR; + +/** + * Gear VR controls. + * Interface with Gear VR controller and map Gamepad events to + * controller buttons: trackpad, trigger + * Load a controller model and highlight the pressed buttons. + */ +module.exports.Component = registerComponent('gearvr-controls', { + schema: { + hand: { + default: '' + }, + // This informs the degenerate arm model. + buttonColor: { + type: 'color', + default: '#000000' + }, + buttonTouchedColor: { + type: 'color', + default: '#777777' + }, + buttonHighlightColor: { + type: 'color', + default: '#FFFFFF' + }, + model: { + default: true + }, + orientationOffset: { + type: 'vec3' + }, + armModel: { + default: true + } + }, + mapping: INPUT_MAPPING, + bindMethods: function () { + this.onModelLoaded = bind(this.onModelLoaded, this); + this.onControllersUpdate = bind(this.onControllersUpdate, this); + this.checkIfControllerPresent = bind(this.checkIfControllerPresent, this); + this.removeControllersUpdateListener = bind(this.removeControllersUpdateListener, this); + this.onAxisMoved = bind(this.onAxisMoved, this); + }, + init: function () { + var self = this; + this.onButtonChanged = bind(this.onButtonChanged, this); + this.onButtonDown = function (evt) { + onButtonEvent(evt.detail.id, 'down', self); + }; + this.onButtonUp = function (evt) { + onButtonEvent(evt.detail.id, 'up', self); + }; + this.onButtonTouchStart = function (evt) { + onButtonEvent(evt.detail.id, 'touchstart', self); + }; + this.onButtonTouchEnd = function (evt) { + onButtonEvent(evt.detail.id, 'touchend', self); + }; + this.controllerPresent = false; + this.lastControllerCheck = 0; + this.bindMethods(); + }, + addEventListeners: function () { + var el = this.el; + el.addEventListener('buttonchanged', this.onButtonChanged); + el.addEventListener('buttondown', this.onButtonDown); + el.addEventListener('buttonup', this.onButtonUp); + el.addEventListener('touchstart', this.onButtonTouchStart); + el.addEventListener('touchend', this.onButtonTouchEnd); + el.addEventListener('model-loaded', this.onModelLoaded); + el.addEventListener('axismove', this.onAxisMoved); + this.controllerEventsActive = true; + }, + removeEventListeners: function () { + var el = this.el; + el.removeEventListener('buttonchanged', this.onButtonChanged); + el.removeEventListener('buttondown', this.onButtonDown); + el.removeEventListener('buttonup', this.onButtonUp); + el.removeEventListener('touchstart', this.onButtonTouchStart); + el.removeEventListener('touchend', this.onButtonTouchEnd); + el.removeEventListener('model-loaded', this.onModelLoaded); + el.removeEventListener('axismove', this.onAxisMoved); + this.controllerEventsActive = false; + }, + checkIfControllerPresent: function () { + checkControllerPresentAndSetup(this, GAMEPAD_ID_PREFIX, this.data.hand ? { + hand: this.data.hand + } : {}); + }, + play: function () { + this.checkIfControllerPresent(); + this.addControllersUpdateListener(); + }, + pause: function () { + this.removeEventListeners(); + this.removeControllersUpdateListener(); + }, + injectTrackedControls: function () { + var el = this.el; + var data = this.data; + el.setAttribute('tracked-controls', { + armModel: data.armModel, + hand: data.hand, + idPrefix: GAMEPAD_ID_PREFIX, + id: GAMEPAD_ID_PREFIX, + orientationOffset: data.orientationOffset + }); + if (!this.data.model) { + return; + } + this.el.setAttribute('obj-model', { + obj: GEARVR_CONTROLLER_MODEL_OBJ_URL, + mtl: GEARVR_CONTROLLER_MODEL_OBJ_MTL + }); + }, + addControllersUpdateListener: function () { + this.el.sceneEl.addEventListener('controllersupdated', this.onControllersUpdate, false); + }, + removeControllersUpdateListener: function () { + this.el.sceneEl.removeEventListener('controllersupdated', this.onControllersUpdate, false); + }, + onControllersUpdate: function () { + this.checkIfControllerPresent(); + }, + // No need for onButtonChanged, since Gear VR controller has no analog buttons. + + onModelLoaded: function (evt) { + var controllerObject3D = evt.detail.model; + var buttonMeshes; + if (!this.data.model) { + return; + } + buttonMeshes = this.buttonMeshes = {}; + buttonMeshes.trigger = controllerObject3D.children[2]; + buttonMeshes.trackpad = controllerObject3D.children[1]; + buttonMeshes.touchpad = controllerObject3D.children[1]; + }, + onButtonChanged: function (evt) { + var button = this.mapping.buttons[evt.detail.id]; + if (!button) return; + // Pass along changed event with button state, using button mapping for convenience. + this.el.emit(button + 'changed', evt.detail.state); + }, + onAxisMoved: function (evt) { + emitIfAxesChanged(this, this.mapping.axes, evt); + }, + updateModel: function (buttonName, evtName) { + if (!this.data.model) { + return; + } + this.updateButtonModel(buttonName, evtName); + }, + updateButtonModel: function (buttonName, state) { + var buttonMeshes = this.buttonMeshes; + if (!buttonMeshes || !buttonMeshes[buttonName]) { + return; + } + var color; + switch (state) { + case 'down': + color = this.data.buttonHighlightColor; + break; + case 'touchstart': + color = this.data.buttonTouchedColor; + break; + default: + color = this.data.buttonColor; + } + buttonMeshes[buttonName].material.color.set(color); + } +}); + +/***/ }), + +/***/ "./src/components/generic-tracked-controller-controls.js": +/*!***************************************************************!*\ + !*** ./src/components/generic-tracked-controller-controls.js ***! + \***************************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var bind = __webpack_require__(/*! ../utils/bind */ "./src/utils/bind.js"); +var trackedControlsUtils = __webpack_require__(/*! ../utils/tracked-controls */ "./src/utils/tracked-controls.js"); +var checkControllerPresentAndSetup = trackedControlsUtils.checkControllerPresentAndSetup; +var emitIfAxesChanged = trackedControlsUtils.emitIfAxesChanged; +var onButtonEvent = trackedControlsUtils.onButtonEvent; +var GAMEPAD_ID_PREFIX = 'generic'; + +/** + * Button indices: + * 0 - trigger + * 1 - squeeze + * 2 - touchpad + * 3 - thumbstick + * + * Axis: + * 0 - touchpad + * 1 - thumbstick + * + */ +var INPUT_MAPPING = { + axes: { + touchpad: [0, 1], + thumbstick: [2, 3] + }, + buttons: ['trigger', 'squeeze', 'touchpad', 'thumbstick'] +}; + +/** + * Oculus Go controls. + * Interface with Oculus Go controller and map Gamepad events to + * controller buttons: trackpad, trigger + * Load a controller model and highlight the pressed buttons. + */ +module.exports.Component = registerComponent('generic-tracked-controller-controls', { + schema: { + hand: { + default: '' + }, + // This informs the degenerate arm model. + defaultModel: { + default: true + }, + defaultModelColor: { + default: 'gray' + }, + orientationOffset: { + type: 'vec3' + }, + disabled: { + default: false + } + }, + /** + * Button IDs: + * 0 - trackpad + * 1 - trigger + */ + mapping: INPUT_MAPPING, + bindMethods: function () { + this.onControllersUpdate = bind(this.onControllersUpdate, this); + this.checkIfControllerPresent = bind(this.checkIfControllerPresent, this); + this.removeControllersUpdateListener = bind(this.removeControllersUpdateListener, this); + this.onAxisMoved = bind(this.onAxisMoved, this); + }, + init: function () { + var self = this; + this.onButtonChanged = bind(this.onButtonChanged, this); + this.onButtonDown = function (evt) { + onButtonEvent(evt.detail.id, 'down', self); + }; + this.onButtonUp = function (evt) { + onButtonEvent(evt.detail.id, 'up', self); + }; + this.onButtonTouchStart = function (evt) { + onButtonEvent(evt.detail.id, 'touchstart', self); + }; + this.onButtonTouchEnd = function (evt) { + onButtonEvent(evt.detail.id, 'touchend', self); + }; + this.controllerPresent = false; + this.wasControllerConnected = false; + this.lastControllerCheck = 0; + this.rendererSystem = this.el.sceneEl.systems.renderer; + this.bindMethods(); + + // generic-tracked-controller-controls has the lowest precedence. + // We must diable this component if there are more specialized controls components. + this.el.addEventListener('controllerconnected', function (evt) { + if (evt.detail.name === self.name) { + return; + } + self.wasControllerConnected = true; + self.removeEventListeners(); + self.removeControllersUpdateListener(); + }); + }, + addEventListeners: function () { + var el = this.el; + el.addEventListener('buttonchanged', this.onButtonChanged); + el.addEventListener('buttondown', this.onButtonDown); + el.addEventListener('buttonup', this.onButtonUp); + el.addEventListener('touchstart', this.onButtonTouchStart); + el.addEventListener('touchend', this.onButtonTouchEnd); + el.addEventListener('axismove', this.onAxisMoved); + this.controllerEventsActive = true; + }, + removeEventListeners: function () { + var el = this.el; + el.removeEventListener('buttonchanged', this.onButtonChanged); + el.removeEventListener('buttondown', this.onButtonDown); + el.removeEventListener('buttonup', this.onButtonUp); + el.removeEventListener('touchstart', this.onButtonTouchStart); + el.removeEventListener('touchend', this.onButtonTouchEnd); + el.removeEventListener('axismove', this.onAxisMoved); + this.controllerEventsActive = false; + }, + checkIfControllerPresent: function () { + var data = this.data; + var hand = data.hand ? data.hand : undefined; + checkControllerPresentAndSetup(this, GAMEPAD_ID_PREFIX, { + hand: hand, + iterateControllerProfiles: true + }); + }, + play: function () { + if (this.wasControllerConnected) { + return; + } + this.checkIfControllerPresent(); + this.addControllersUpdateListener(); + }, + pause: function () { + this.removeEventListeners(); + this.removeControllersUpdateListener(); + }, + injectTrackedControls: function () { + var el = this.el; + var data = this.data; + + // Do nothing if tracked-controls already set. + // Generic controls have the lowest precedence. + if (this.el.components['tracked-controls']) { + this.removeEventListeners(); + return; + } + el.setAttribute('tracked-controls', { + hand: data.hand, + idPrefix: GAMEPAD_ID_PREFIX, + orientationOffset: data.orientationOffset, + iterateControllerProfiles: true + }); + if (!this.data.defaultModel) { + return; + } + this.initDefaultModel(); + }, + addControllersUpdateListener: function () { + this.el.sceneEl.addEventListener('controllersupdated', this.onControllersUpdate, false); + }, + removeControllersUpdateListener: function () { + this.el.sceneEl.removeEventListener('controllersupdated', this.onControllersUpdate, false); + }, + onControllersUpdate: function () { + this.checkIfControllerPresent(); + }, + onButtonChanged: function (evt) { + var button = this.mapping.buttons[evt.detail.id]; + if (!button) return; + // Pass along changed event with button state, using button mapping for convenience. + this.el.emit(button + 'changed', evt.detail.state); + }, + onAxisMoved: function (evt) { + emitIfAxesChanged(this, this.mapping.axes, evt); + }, + initDefaultModel: function () { + var modelEl = this.modelEl = document.createElement('a-entity'); + modelEl.setAttribute('geometry', { + primitive: 'sphere', + radius: 0.03 + }); + modelEl.setAttribute('material', { + color: this.data.color + }); + this.el.appendChild(modelEl); + } +}); + +/***/ }), + +/***/ "./src/components/geometry.js": +/*!************************************!*\ + !*** ./src/components/geometry.js ***! + \************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var geometries = (__webpack_require__(/*! ../core/geometry */ "./src/core/geometry.js").geometries); +var geometryNames = (__webpack_require__(/*! ../core/geometry */ "./src/core/geometry.js").geometryNames); +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var THREE = __webpack_require__(/*! ../lib/three */ "./src/lib/three.js"); +var dummyGeometry = new THREE.BufferGeometry(); + +/** + * Geometry component. Combined with material component to make a mesh in 3D object. + * Extended with registered geometries. + */ +module.exports.Component = registerComponent('geometry', { + schema: { + buffer: { + default: true + }, + primitive: { + default: 'box', + oneOf: geometryNames, + schemaChange: true + }, + skipCache: { + default: false + } + }, + init: function () { + this.geometry = null; + }, + /** + * Talk to geometry system to get or create geometry. + */ + update: function (previousData) { + var data = this.data; + var el = this.el; + var mesh; + var system = this.system; + + // Dispose old geometry if we created one. + if (this.geometry) { + system.unuseGeometry(previousData); + this.geometry = null; + } + + // Create new geometry. + this.geometry = system.getOrCreateGeometry(data); + + // Set on mesh. If mesh does not exist, create it. + mesh = el.getObject3D('mesh'); + if (mesh) { + mesh.geometry = this.geometry; + } else { + mesh = new THREE.Mesh(); + mesh.geometry = this.geometry; + // Default material if not defined on the entity. + if (!this.el.getAttribute('material')) { + mesh.material = new THREE.MeshStandardMaterial({ + color: Math.random() * 0xFFFFFF, + metalness: 0, + roughness: 0.5 + }); + } + el.setObject3D('mesh', mesh); + } + }, + /** + * Tell geometry system that entity is no longer using the geometry. + * Unset the geometry on the mesh + */ + remove: function () { + this.system.unuseGeometry(this.data); + this.el.getObject3D('mesh').geometry = dummyGeometry; + this.geometry = null; + }, + /** + * Update geometry component schema based on geometry type. + */ + updateSchema: function (data) { + var currentGeometryType = this.oldData && this.oldData.primitive; + var newGeometryType = data.primitive; + var schema = geometries[newGeometryType] && geometries[newGeometryType].schema; + + // Geometry has no schema. + if (!schema) { + throw new Error('Unknown geometry schema `' + newGeometryType + '`'); + } + // Nothing has changed. + if (currentGeometryType && currentGeometryType === newGeometryType) { + return; + } + this.extendSchema(schema); + } +}); + +/***/ }), + +/***/ "./src/components/gltf-model.js": +/*!**************************************!*\ + !*** ./src/components/gltf-model.js ***! + \**************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var THREE = __webpack_require__(/*! ../lib/three */ "./src/lib/three.js"); +var utils = __webpack_require__(/*! ../utils/ */ "./src/utils/index.js"); +var warn = utils.debug('components:gltf-model:warn'); + +/** + * glTF model loader. + */ +module.exports.Component = registerComponent('gltf-model', { + schema: { + type: 'model' + }, + init: function () { + var self = this; + var dracoLoader = this.system.getDRACOLoader(); + var meshoptDecoder = this.system.getMeshoptDecoder(); + var ktxLoader = this.system.getKTX2Loader(); + this.model = null; + this.loader = new THREE.GLTFLoader(); + if (dracoLoader) { + this.loader.setDRACOLoader(dracoLoader); + } + if (meshoptDecoder) { + this.ready = meshoptDecoder.then(function (meshoptDecoder) { + self.loader.setMeshoptDecoder(meshoptDecoder); + }); + } else { + this.ready = Promise.resolve(); + } + if (ktxLoader) { + this.loader.setKTX2Loader(ktxLoader); + } + }, + update: function () { + var self = this; + var el = this.el; + var src = this.data; + if (!src) { + return; + } + this.remove(); + this.ready.then(function () { + self.loader.load(src, function gltfLoaded(gltfModel) { + self.model = gltfModel.scene || gltfModel.scenes[0]; + self.model.animations = gltfModel.animations; + el.setObject3D('mesh', self.model); + el.emit('model-loaded', { + format: 'gltf', + model: self.model + }); + }, undefined /* onProgress */, function gltfFailed(error) { + var message = error && error.message ? error.message : 'Failed to load glTF model'; + warn(message); + el.emit('model-error', { + format: 'gltf', + src: src + }); + }); + }); + }, + remove: function () { + if (!this.model) { + return; + } + this.el.removeObject3D('mesh'); + } +}); + +/***/ }), + +/***/ "./src/components/hand-controls.js": +/*!*****************************************!*\ + !*** ./src/components/hand-controls.js ***! + \*****************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/* global THREE */ +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); + +// Found at https://github.com/aframevr/assets. +var MODEL_URLS = { + toonLeft: 'https://cdn.aframe.io/controllers/hands/leftHand.glb', + toonRight: 'https://cdn.aframe.io/controllers/hands/rightHand.glb', + lowPolyLeft: 'https://cdn.aframe.io/controllers/hands/leftHandLow.glb', + lowPolyRight: 'https://cdn.aframe.io/controllers/hands/rightHandLow.glb', + highPolyLeft: 'https://cdn.aframe.io/controllers/hands/leftHandHigh.glb', + highPolyRight: 'https://cdn.aframe.io/controllers/hands/rightHandHigh.glb' +}; + +// Poses. +var ANIMATIONS = { + open: 'Open', + // point: grip active, trackpad surface active, trigger inactive. + point: 'Point', + // pointThumb: grip active, trigger inactive, trackpad surface inactive. + pointThumb: 'Point + Thumb', + // fist: grip active, trigger active, trackpad surface active. + fist: 'Fist', + // hold: trigger active, grip inactive. + hold: 'Hold', + // thumbUp: grip active, trigger active, trackpad surface inactive. + thumbUp: 'Thumb Up' +}; + +// Map animation to public events for the API. +var EVENTS = {}; +EVENTS[ANIMATIONS.fist] = 'grip'; +EVENTS[ANIMATIONS.thumbUp] = 'pistol'; +EVENTS[ANIMATIONS.point] = 'pointing'; + +/** + * Hand controls component that abstracts 6DoF controls: + * oculus-touch-controls, vive-controls, windows-motion-controls. + * + * Originally meant to be a sample implementation of applications-specific controls that + * abstracts multiple types of controllers. + * + * Auto-detect appropriate controller. + * Handle common events coming from the detected vendor-specific controls. + * Translate button events to semantic hand-related event names: + * (gripclose, gripopen, thumbup, thumbdown, pointup, pointdown) + * Load hand model with gestures that are applied based on the button pressed. + * + * @property {string} Hand mapping (`left`, `right`). + */ +module.exports.Component = registerComponent('hand-controls', { + schema: { + color: { + default: 'white', + type: 'color' + }, + hand: { + default: 'left' + }, + handModelStyle: { + default: 'lowPoly', + oneOf: ['lowPoly', 'highPoly', 'toon'] + } + }, + init: function () { + var self = this; + var el = this.el; + // Current pose. + this.gesture = ANIMATIONS.open; + // Active buttons populated by events provided by the attached controls. + this.pressedButtons = {}; + this.touchedButtons = {}; + this.loader = new THREE.GLTFLoader(); + this.loader.setCrossOrigin('anonymous'); + this.onGripDown = function () { + self.handleButton('grip', 'down'); + }; + this.onGripUp = function () { + self.handleButton('grip', 'up'); + }; + this.onTrackpadDown = function () { + self.handleButton('trackpad', 'down'); + }; + this.onTrackpadUp = function () { + self.handleButton('trackpad', 'up'); + }; + this.onTrackpadTouchStart = function () { + self.handleButton('trackpad', 'touchstart'); + }; + this.onTrackpadTouchEnd = function () { + self.handleButton('trackpad', 'touchend'); + }; + this.onTriggerDown = function () { + self.handleButton('trigger', 'down'); + }; + this.onTriggerUp = function () { + self.handleButton('trigger', 'up'); + }; + this.onTriggerTouchStart = function () { + self.handleButton('trigger', 'touchstart'); + }; + this.onTriggerTouchEnd = function () { + self.handleButton('trigger', 'touchend'); + }; + this.onGripTouchStart = function () { + self.handleButton('grip', 'touchstart'); + }; + this.onGripTouchEnd = function () { + self.handleButton('grip', 'touchend'); + }; + this.onThumbstickDown = function () { + self.handleButton('thumbstick', 'down'); + }; + this.onThumbstickUp = function () { + self.handleButton('thumbstick', 'up'); + }; + this.onAorXTouchStart = function () { + self.handleButton('AorX', 'touchstart'); + }; + this.onAorXTouchEnd = function () { + self.handleButton('AorX', 'touchend'); + }; + this.onBorYTouchStart = function () { + self.handleButton('BorY', 'touchstart'); + }; + this.onBorYTouchEnd = function () { + self.handleButton('BorY', 'touchend'); + }; + this.onSurfaceTouchStart = function () { + self.handleButton('surface', 'touchstart'); + }; + this.onSurfaceTouchEnd = function () { + self.handleButton('surface', 'touchend'); + }; + this.onControllerConnected = this.onControllerConnected.bind(this); + this.onControllerDisconnected = this.onControllerDisconnected.bind(this); + el.addEventListener('controllerconnected', this.onControllerConnected); + el.addEventListener('controllerdisconnected', this.onControllerDisconnected); + + // Hidden by default. + el.object3D.visible = false; + }, + play: function () { + this.addEventListeners(); + }, + pause: function () { + this.removeEventListeners(); + }, + tick: function (time, delta) { + var mesh = this.el.getObject3D('mesh'); + if (!mesh || !mesh.mixer) { + return; + } + mesh.mixer.update(delta / 1000); + }, + onControllerConnected: function () { + this.el.object3D.visible = true; + }, + onControllerDisconnected: function () { + this.el.object3D.visible = false; + }, + addEventListeners: function () { + var el = this.el; + el.addEventListener('gripdown', this.onGripDown); + el.addEventListener('gripup', this.onGripUp); + el.addEventListener('trackpaddown', this.onTrackpadDown); + el.addEventListener('trackpadup', this.onTrackpadUp); + el.addEventListener('trackpadtouchstart', this.onTrackpadTouchStart); + el.addEventListener('trackpadtouchend', this.onTrackpadTouchEnd); + el.addEventListener('triggerdown', this.onTriggerDown); + el.addEventListener('triggerup', this.onTriggerUp); + el.addEventListener('triggertouchstart', this.onTriggerTouchStart); + el.addEventListener('triggertouchend', this.onTriggerTouchEnd); + el.addEventListener('griptouchstart', this.onGripTouchStart); + el.addEventListener('griptouchend', this.onGripTouchEnd); + el.addEventListener('thumbstickdown', this.onThumbstickDown); + el.addEventListener('thumbstickup', this.onThumbstickUp); + el.addEventListener('abuttontouchstart', this.onAorXTouchStart); + el.addEventListener('abuttontouchend', this.onAorXTouchEnd); + el.addEventListener('bbuttontouchstart', this.onBorYTouchStart); + el.addEventListener('bbuttontouchend', this.onBorYTouchEnd); + el.addEventListener('xbuttontouchstart', this.onAorXTouchStart); + el.addEventListener('xbuttontouchend', this.onAorXTouchEnd); + el.addEventListener('ybuttontouchstart', this.onBorYTouchStart); + el.addEventListener('ybuttontouchend', this.onBorYTouchEnd); + el.addEventListener('surfacetouchstart', this.onSurfaceTouchStart); + el.addEventListener('surfacetouchend', this.onSurfaceTouchEnd); + }, + removeEventListeners: function () { + var el = this.el; + el.removeEventListener('gripdown', this.onGripDown); + el.removeEventListener('gripup', this.onGripUp); + el.removeEventListener('trackpaddown', this.onTrackpadDown); + el.removeEventListener('trackpadup', this.onTrackpadUp); + el.removeEventListener('trackpadtouchstart', this.onTrackpadTouchStart); + el.removeEventListener('trackpadtouchend', this.onTrackpadTouchEnd); + el.removeEventListener('triggerdown', this.onTriggerDown); + el.removeEventListener('triggerup', this.onTriggerUp); + el.removeEventListener('triggertouchstart', this.onTriggerTouchStart); + el.removeEventListener('triggertouchend', this.onTriggerTouchEnd); + el.removeEventListener('griptouchstart', this.onGripTouchStart); + el.removeEventListener('griptouchend', this.onGripTouchEnd); + el.removeEventListener('thumbstickdown', this.onThumbstickDown); + el.removeEventListener('thumbstickup', this.onThumbstickUp); + el.removeEventListener('abuttontouchstart', this.onAorXTouchStart); + el.removeEventListener('abuttontouchend', this.onAorXTouchEnd); + el.removeEventListener('bbuttontouchstart', this.onBorYTouchStart); + el.removeEventListener('bbuttontouchend', this.onBorYTouchEnd); + el.removeEventListener('xbuttontouchstart', this.onAorXTouchStart); + el.removeEventListener('xbuttontouchend', this.onAorXTouchEnd); + el.removeEventListener('ybuttontouchstart', this.onBorYTouchStart); + el.removeEventListener('ybuttontouchend', this.onBorYTouchEnd); + el.removeEventListener('surfacetouchstart', this.onSurfaceTouchStart); + el.removeEventListener('surfacetouchend', this.onSurfaceTouchEnd); + }, + /** + * Update handler. More like the `init` handler since the only property is the hand, and + * that won't be changing much. + */ + update: function (previousHand) { + var controlConfiguration; + var el = this.el; + var hand = this.data.hand; + var handModelStyle = this.data.handModelStyle; + var handColor = this.data.color; + var self = this; + + // Get common configuration to abstract different vendor controls. + controlConfiguration = { + hand: hand, + model: false + }; + + // Set model. + if (hand !== previousHand) { + var handmodelUrl = MODEL_URLS[handModelStyle + hand.charAt(0).toUpperCase() + hand.slice(1)]; + this.loader.load(handmodelUrl, function (gltf) { + var mesh = gltf.scene.children[0]; + var handModelOrientation = hand === 'left' ? Math.PI / 2 : -Math.PI / 2; + mesh.mixer = new THREE.AnimationMixer(mesh); + self.clips = gltf.animations; + el.setObject3D('mesh', mesh); + var handMaterial = mesh.children[1].material; + handMaterial.color = new THREE.Color(handColor); + mesh.position.set(0, 0, 0); + mesh.rotation.set(0, 0, handModelOrientation); + el.setAttribute('magicleap-controls', controlConfiguration); + el.setAttribute('vive-controls', controlConfiguration); + el.setAttribute('oculus-touch-controls', controlConfiguration); + el.setAttribute('windows-motion-controls', controlConfiguration); + el.setAttribute('hp-mixed-reality-controls', controlConfiguration); + }); + } + }, + remove: function () { + this.el.removeObject3D('mesh'); + }, + /** + * Play model animation, based on which button was pressed and which kind of event. + * + * 1. Process buttons. + * 2. Determine gesture (this.determineGesture()). + * 3. Animation gesture (this.animationGesture()). + * 4. Emit gesture events (this.emitGestureEvents()). + * + * @param {string} button - Name of the button. + * @param {string} evt - Type of event for the button (i.e., down/up/touchstart/touchend). + */ + handleButton: function (button, evt) { + var lastGesture; + var isPressed = evt === 'down'; + var isTouched = evt === 'touchstart'; + + // Update objects. + if (evt.indexOf('touch') === 0) { + // Update touch object. + if (isTouched === this.touchedButtons[button]) { + return; + } + this.touchedButtons[button] = isTouched; + } else { + // Update button object. + if (isPressed === this.pressedButtons[button]) { + return; + } + this.pressedButtons[button] = isPressed; + } + + // Determine the gesture. + lastGesture = this.gesture; + this.gesture = this.determineGesture(); + + // Same gesture. + if (this.gesture === lastGesture) { + return; + } + // Animate gesture. + this.animateGesture(this.gesture, lastGesture); + + // Emit events. + this.emitGestureEvents(this.gesture, lastGesture); + }, + /** + * Determine which pose hand should be in considering active and touched buttons. + */ + determineGesture: function () { + var gesture; + var isGripActive = this.pressedButtons.grip; + var isSurfaceActive = this.pressedButtons.surface || this.touchedButtons.surface; + var isTrackpadActive = this.pressedButtons.trackpad || this.touchedButtons.trackpad; + var isTriggerActive = this.pressedButtons.trigger || this.touchedButtons.trigger; + var isABXYActive = this.touchedButtons.AorX || this.touchedButtons.BorY; + var isVive = isViveController(this.el.components['tracked-controls']); + + // Works well with Oculus Touch and Windows Motion Controls, but Vive needs tweaks. + if (isVive) { + if (isGripActive || isTriggerActive) { + gesture = ANIMATIONS.fist; + } else if (isTrackpadActive) { + gesture = ANIMATIONS.point; + } + } else { + if (isGripActive) { + if (isSurfaceActive || isABXYActive || isTrackpadActive) { + gesture = isTriggerActive ? ANIMATIONS.fist : ANIMATIONS.point; + } else { + gesture = isTriggerActive ? ANIMATIONS.thumbUp : ANIMATIONS.pointThumb; + } + } else if (isTriggerActive) { + gesture = ANIMATIONS.hold; + } + } + return gesture; + }, + /** + * Play corresponding clip to a gesture + */ + getClip: function (gesture) { + var clip; + var i; + for (i = 0; i < this.clips.length; i++) { + clip = this.clips[i]; + if (clip.name !== gesture) { + continue; + } + return clip; + } + }, + /** + * Play gesture animation. + * + * @param {string} gesture - Which pose to animate to. If absent, then animate to open. + * @param {string} lastGesture - Previous gesture, to reverse back to open if needed. + */ + animateGesture: function (gesture, lastGesture) { + if (gesture) { + this.playAnimation(gesture || ANIMATIONS.open, lastGesture, false); + return; + } + + // If no gesture, then reverse the current gesture back to open pose. + this.playAnimation(lastGesture, lastGesture, true); + }, + /** + * Emit `hand-controls`-specific events. + */ + emitGestureEvents: function (gesture, lastGesture) { + var el = this.el; + var eventName; + if (lastGesture === gesture) { + return; + } + + // Emit event for lastGesture not inactive. + eventName = getGestureEventName(lastGesture, false); + if (eventName) { + el.emit(eventName); + } + + // Emit event for current gesture now active. + eventName = getGestureEventName(gesture, true); + if (eventName) { + el.emit(eventName); + } + }, + /** + * Play hand animation based on button state. + * + * @param {string} gesture - Name of the animation as specified by the model. + * @param {string} lastGesture - Previous pose. + * @param {boolean} reverse - Whether animation should play in reverse. + */ + playAnimation: function (gesture, lastGesture, reverse) { + var clip; + var fromAction; + var mesh = this.el.getObject3D('mesh'); + var toAction; + if (!mesh) { + return; + } + + // Stop all current animations. + mesh.mixer.stopAllAction(); + + // Grab clip action. + clip = this.getClip(gesture); + toAction = mesh.mixer.clipAction(clip); + toAction.clampWhenFinished = true; + toAction.loop = THREE.LoopRepeat; + toAction.repetitions = 0; + toAction.timeScale = reverse ? -1 : 1; + toAction.time = reverse ? clip.duration : 0; + toAction.weight = 1; + + // No gesture to gesture or gesture to no gesture. + if (!lastGesture || gesture === lastGesture) { + // Stop all current animations. + mesh.mixer.stopAllAction(); + // Play animation. + toAction.play(); + return; + } + + // Animate or crossfade from gesture to gesture. + clip = this.getClip(lastGesture); + fromAction = mesh.mixer.clipAction(clip); + fromAction.weight = 0.15; + fromAction.play(); + toAction.play(); + fromAction.crossFadeTo(toAction, 0.15, true); + } +}); + +/** + * Suffix gestures based on toggle state (e.g., open/close, up/down, start/end). + * + * @param {string} gesture + * @param {boolean} active + */ +function getGestureEventName(gesture, active) { + var eventName; + if (!gesture) { + return; + } + eventName = EVENTS[gesture]; + if (eventName === 'grip') { + return eventName + (active ? 'close' : 'open'); + } + if (eventName === 'point') { + return eventName + (active ? 'up' : 'down'); + } + if (eventName === 'pointing' || eventName === 'pistol') { + return eventName + (active ? 'start' : 'end'); + } +} +function isViveController(trackedControls) { + var controller = trackedControls && trackedControls.controller; + var isVive = controller && (controller.id && controller.id.indexOf('OpenVR ') === 0 || controller.profiles && controller.profiles[0] && controller.profiles[0] === 'htc-vive'); + return isVive; +} + +/***/ }), + +/***/ "./src/components/hand-tracking-controls.js": +/*!**************************************************!*\ + !*** ./src/components/hand-tracking-controls.js ***! + \**************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/* global THREE, XRRigidTransform */ +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var bind = __webpack_require__(/*! ../utils/bind */ "./src/utils/bind.js"); +var trackedControlsUtils = __webpack_require__(/*! ../utils/tracked-controls */ "./src/utils/tracked-controls.js"); +var checkControllerPresentAndSetup = trackedControlsUtils.checkControllerPresentAndSetup; +var LEFT_HAND_MODEL_URL = 'https://cdn.aframe.io/controllers/oculus-hands/v4/left.glb'; +var RIGHT_HAND_MODEL_URL = 'https://cdn.aframe.io/controllers/oculus-hands/v4/right.glb'; +var JOINTS = ['wrist', 'thumb-metacarpal', 'thumb-phalanx-proximal', 'thumb-phalanx-distal', 'thumb-tip', 'index-finger-metacarpal', 'index-finger-phalanx-proximal', 'index-finger-phalanx-intermediate', 'index-finger-phalanx-distal', 'index-finger-tip', 'middle-finger-metacarpal', 'middle-finger-phalanx-proximal', 'middle-finger-phalanx-intermediate', 'middle-finger-phalanx-distal', 'middle-finger-tip', 'ring-finger-metacarpal', 'ring-finger-phalanx-proximal', 'ring-finger-phalanx-intermediate', 'ring-finger-phalanx-distal', 'ring-finger-tip', 'pinky-finger-metacarpal', 'pinky-finger-phalanx-proximal', 'pinky-finger-phalanx-intermediate', 'pinky-finger-phalanx-distal', 'pinky-finger-tip']; +var PINCH_START_DISTANCE = 0.015; +var PINCH_END_DISTANCE = 0.03; +var PINCH_POSITION_INTERPOLATION = 0.5; + +/** + * Controls for hand tracking + */ +module.exports.Component = registerComponent('hand-tracking-controls', { + schema: { + hand: { + default: 'right', + oneOf: ['left', 'right'] + }, + modelStyle: { + default: 'mesh', + oneOf: ['dots', 'mesh'] + }, + modelColor: { + default: 'white' + } + }, + bindMethods: function () { + this.onControllersUpdate = bind(this.onControllersUpdate, this); + this.checkIfControllerPresent = bind(this.checkIfControllerPresent, this); + this.removeControllersUpdateListener = bind(this.removeControllersUpdateListener, this); + }, + addEventListeners: function () { + this.el.addEventListener('model-loaded', this.onModelLoaded); + for (var i = 0; i < this.jointEls.length; ++i) { + this.jointEls[i].object3D.visible = true; + } + }, + removeEventListeners: function () { + this.el.removeEventListener('model-loaded', this.onModelLoaded); + for (var i = 0; i < this.jointEls.length; ++i) { + this.jointEls[i].object3D.visible = false; + } + }, + init: function () { + var sceneEl = this.el.sceneEl; + var webXROptionalAttributes = sceneEl.getAttribute('webxr').optionalFeatures; + webXROptionalAttributes.push('hand-tracking'); + sceneEl.setAttribute('webxr', { + optionalFeatures: webXROptionalAttributes + }); + this.onModelLoaded = this.onModelLoaded.bind(this); + this.jointEls = []; + this.controllerPresent = false; + this.isPinched = false; + this.pinchEventDetail = { + position: new THREE.Vector3() + }; + this.indexTipPosition = new THREE.Vector3(); + this.bindMethods(); + this.updateReferenceSpace = this.updateReferenceSpace.bind(this); + this.el.sceneEl.addEventListener('enter-vr', this.updateReferenceSpace); + this.el.sceneEl.addEventListener('exit-vr', this.updateReferenceSpace); + }, + updateReferenceSpace: function () { + var self = this; + var xrSession = this.el.sceneEl.xrSession; + this.referenceSpace = undefined; + if (!xrSession) { + return; + } + var referenceSpaceType = self.el.sceneEl.systems.webxr.sessionReferenceSpaceType; + xrSession.requestReferenceSpace(referenceSpaceType).then(function (referenceSpace) { + self.referenceSpace = referenceSpace.getOffsetReferenceSpace(new XRRigidTransform({ + x: 0, + y: 1.5, + z: 0 + })); + }).catch(function (error) { + self.el.sceneEl.systems.webxr.warnIfFeatureNotRequested(referenceSpaceType, 'tracked-controls-webxr uses reference space ' + referenceSpaceType); + throw error; + }); + }, + checkIfControllerPresent: function () { + var data = this.data; + var hand = data.hand ? data.hand : undefined; + checkControllerPresentAndSetup(this, '', { + hand: hand, + iterateControllerProfiles: true, + handTracking: true + }); + }, + play: function () { + this.checkIfControllerPresent(); + this.addControllersUpdateListener(); + }, + tick: function () { + var sceneEl = this.el.sceneEl; + var controller = this.el.components['tracked-controls'] && this.el.components['tracked-controls'].controller; + var frame = sceneEl.frame; + var trackedControlsWebXR = this.el.components['tracked-controls-webxr']; + if (!controller || !frame || !trackedControlsWebXR) { + return; + } + if (controller.hand) { + this.el.object3D.position.set(0, 0, 0); + this.el.object3D.rotation.set(0, 0, 0); + if (frame.getJointPose) { + this.updateHandModel(); + } + this.detectGesture(); + } + }, + updateHandModel: function () { + if (this.data.modelStyle === 'dots') { + this.updateHandDotsModel(); + } + if (this.data.modelStyle === 'mesh') { + this.updateHandMeshModel(); + } + }, + getBone: function (name) { + var bones = this.bones; + for (var i = 0; i < bones.length; i++) { + if (bones[i].name === name) { + return bones[i]; + } + } + return null; + }, + updateHandMeshModel: function () { + var frame = this.el.sceneEl.frame; + var controller = this.el.components['tracked-controls'] && this.el.components['tracked-controls'].controller; + var referenceSpace = this.referenceSpace; + if (!controller || !this.mesh || !referenceSpace) { + return; + } + this.mesh.visible = false; + for (var inputjoint of controller.hand.values()) { + var bone; + var jointPose; + var jointTransform; + jointPose = frame.getJointPose(inputjoint, referenceSpace); + bone = this.getBone(inputjoint.jointName); + if (bone != null && jointPose) { + jointTransform = jointPose.transform; + this.mesh.visible = true; + bone.position.copy(jointTransform.position); + bone.quaternion.copy(jointTransform.orientation); + } + } + }, + updateHandDotsModel: function () { + var frame = this.el.sceneEl.frame; + var controller = this.el.components['tracked-controls'] && this.el.components['tracked-controls'].controller; + var trackedControlsWebXR = this.el.components['tracked-controls-webxr']; + var referenceSpace = trackedControlsWebXR.system.referenceSpace; + var jointEl; + var object3D; + var jointPose; + var i = 0; + for (var inputjoint of controller.hand.values()) { + jointEl = this.jointEls[i++]; + object3D = jointEl.object3D; + jointPose = frame.getJointPose(inputjoint, referenceSpace); + jointEl.object3D.visible = !!jointPose; + if (!jointPose) { + continue; + } + object3D.matrix.elements = jointPose.transform.matrix; + object3D.matrix.decompose(object3D.position, object3D.rotation, object3D.scale); + jointEl.setAttribute('scale', { + x: jointPose.radius, + y: jointPose.radius, + z: jointPose.radius + }); + } + }, + detectGesture: function () { + this.detectPinch(); + }, + detectPinch: function () { + var thumbTipPosition = new THREE.Vector3(); + return function () { + var frame = this.el.sceneEl.frame; + var indexTipPosition = this.indexTipPosition; + var controller = this.el.components['tracked-controls'] && this.el.components['tracked-controls'].controller; + var trackedControlsWebXR = this.el.components['tracked-controls-webxr']; + var referenceSpace = this.referenceSpace || trackedControlsWebXR.system.referenceSpace; + var indexTip = controller.hand.get('index-finger-tip'); + var thumbTip = controller.hand.get('thumb-tip'); + if (!indexTip || !thumbTip) { + return; + } + var indexTipPose = frame.getJointPose(indexTip, referenceSpace); + var thumbTipPose = frame.getJointPose(thumbTip, referenceSpace); + if (!indexTipPose || !thumbTipPose) { + return; + } + thumbTipPosition.copy(thumbTipPose.transform.position); + indexTipPosition.copy(indexTipPose.transform.position); + var distance = indexTipPosition.distanceTo(thumbTipPosition); + if (distance < PINCH_START_DISTANCE && this.isPinched === false) { + this.isPinched = true; + this.pinchEventDetail.position.copy(indexTipPosition).lerp(thumbTipPosition, PINCH_POSITION_INTERPOLATION); + this.pinchEventDetail.position.y += 1.5; + this.el.emit('pinchstarted', this.pinchEventDetail); + } + if (distance > PINCH_END_DISTANCE && this.isPinched === true) { + this.isPinched = false; + this.pinchEventDetail.position.copy(indexTipPosition).lerp(thumbTipPosition, PINCH_POSITION_INTERPOLATION); + this.pinchEventDetail.position.y += 1.5; + this.el.emit('pinchended', this.pinchEventDetail); + } + if (this.isPinched) { + this.pinchEventDetail.position.copy(indexTipPosition).lerp(thumbTipPosition, PINCH_POSITION_INTERPOLATION); + this.pinchEventDetail.position.y += 1.5; + this.el.emit('pinchmoved', this.pinchEventDetail); + } + indexTipPosition.y += 1.5; + }; + }(), + pause: function () { + this.removeEventListeners(); + this.removeControllersUpdateListener(); + }, + injectTrackedControls: function () { + var el = this.el; + var data = this.data; + el.setAttribute('tracked-controls', { + hand: data.hand, + iterateControllerProfiles: true, + handTrackingEnabled: true + }); + this.initDefaultModel(); + }, + addControllersUpdateListener: function () { + this.el.sceneEl.addEventListener('controllersupdated', this.onControllersUpdate, false); + }, + removeControllersUpdateListener: function () { + this.el.sceneEl.removeEventListener('controllersupdated', this.onControllersUpdate, false); + }, + onControllersUpdate: function () { + var controller; + this.checkIfControllerPresent(); + controller = this.el.components['tracked-controls'] && this.el.components['tracked-controls'].controller; + if (!this.el.getObject3D('mesh')) { + return; + } + if (!controller || !controller.hand || !controller.hand[0]) { + this.el.getObject3D('mesh').visible = false; + } + }, + initDefaultModel: function () { + if (this.el.getObject3D('mesh')) { + return; + } + if (this.data.modelStyle === 'dots') { + this.initDotsModel(); + } + if (this.data.modelStyle === 'mesh') { + this.initMeshHandModel(); + } + }, + initDotsModel: function () { + // Add models just once. + if (this.jointEls.length !== 0) { + return; + } + for (var i = 0; i < JOINTS.length; ++i) { + var jointEl = this.jointEl = document.createElement('a-entity'); + jointEl.setAttribute('geometry', { + primitive: 'sphere', + radius: 1.0 + }); + jointEl.setAttribute('material', { + color: this.data.modelColor + }); + jointEl.object3D.visible = false; + this.el.appendChild(jointEl); + this.jointEls.push(jointEl); + } + }, + initMeshHandModel: function () { + var modelURL = this.data.hand === 'left' ? LEFT_HAND_MODEL_URL : RIGHT_HAND_MODEL_URL; + this.el.setAttribute('gltf-model', modelURL); + }, + onModelLoaded: function () { + var mesh = this.mesh = this.el.getObject3D('mesh').children[0]; + var skinnedMesh = this.skinnedMesh = mesh.getObjectByProperty('type', 'SkinnedMesh'); + if (!this.skinnedMesh) { + return; + } + this.bones = skinnedMesh.skeleton.bones; + this.el.removeObject3D('mesh'); + mesh.position.set(0, 1.5, 0); + mesh.rotation.set(0, 0, 0); + skinnedMesh.frustumCulled = false; + skinnedMesh.material = new THREE.MeshStandardMaterial({ + skinning: true, + color: this.data.modelColor + }); + this.el.setObject3D('mesh', mesh); + } +}); + +/***/ }), + +/***/ "./src/components/hide-on-enter-ar.js": +/*!********************************************!*\ + !*** ./src/components/hide-on-enter-ar.js ***! + \********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var register = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +module.exports.Component = register('hide-on-enter-ar', { + init: function () { + var self = this; + this.el.sceneEl.addEventListener('enter-vr', function () { + if (self.el.sceneEl.is('ar-mode')) { + self.el.object3D.visible = false; + } + }); + this.el.sceneEl.addEventListener('exit-vr', function () { + self.el.object3D.visible = true; + }); + } +}); + +/***/ }), + +/***/ "./src/components/hp-mixed-reality-controls.js": +/*!*****************************************************!*\ + !*** ./src/components/hp-mixed-reality-controls.js ***! + \*****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var bind = __webpack_require__(/*! ../utils/bind */ "./src/utils/bind.js"); +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var THREE = __webpack_require__(/*! ../lib/three */ "./src/lib/three.js"); +var trackedControlsUtils = __webpack_require__(/*! ../utils/tracked-controls */ "./src/utils/tracked-controls.js"); +var checkControllerPresentAndSetup = trackedControlsUtils.checkControllerPresentAndSetup; +var emitIfAxesChanged = trackedControlsUtils.emitIfAxesChanged; +var onButtonEvent = trackedControlsUtils.onButtonEvent; + +// See Profiles Registry: +// https://github.com/immersive-web/webxr-input-profiles/tree/master/packages/registry +// TODO: Add a more robust system for deriving gamepad name. +var GAMEPAD_ID = 'hp-mixed-reality'; +var HP_MIXEDL_REALITY_MODEL_GLB_BASE_URL = 'https://cdn.aframe.io/controllers/hp/mixed-reality/'; +var HP_MIXED_REALITY_POSITION_OFFSET = { + x: 0, + y: 0, + z: 0.06 +}; +var HP_MIXED_REALITY_ROTATION_OFFSET = { + _x: Math.PI / 4, + _y: 0, + _z: 0, + _order: 'XYZ' +}; + +/** + * Button IDs: + * 0 - trigger + * 1 - grip + * 3 - X / A + * 4 - Y / B + * + * Axis: + * 2 - joystick x axis + * 3 - joystick y axis + */ +var INPUT_MAPPING_WEBXR = { + left: { + axes: { + touchpad: [2, 3] + }, + buttons: ['trigger', 'grip', 'none', 'thumbstick', 'xbutton', 'ybutton'] + }, + right: { + axes: { + touchpad: [2, 3] + }, + buttons: ['trigger', 'grip', 'none', 'thumbstick', 'abutton', 'bbutton'] + } +}; + +/** + * HP Mixed Reality Controls + */ +module.exports.Component = registerComponent('hp-mixed-reality-controls', { + schema: { + hand: { + default: 'none' + }, + model: { + default: true + }, + orientationOffset: { + type: 'vec3' + } + }, + mapping: INPUT_MAPPING_WEBXR, + init: function () { + var self = this; + this.controllerPresent = false; + this.lastControllerCheck = 0; + this.onButtonChanged = bind(this.onButtonChanged, this); + this.onButtonDown = function (evt) { + onButtonEvent(evt.detail.id, 'down', self, self.data.hand); + }; + this.onButtonUp = function (evt) { + onButtonEvent(evt.detail.id, 'up', self, self.data.hand); + }; + this.onButtonTouchEnd = function (evt) { + onButtonEvent(evt.detail.id, 'touchend', self, self.data.hand); + }; + this.onButtonTouchStart = function (evt) { + onButtonEvent(evt.detail.id, 'touchstart', self, self.data.hand); + }; + this.previousButtonValues = {}; + this.rendererSystem = this.el.sceneEl.systems.renderer; + this.bindMethods(); + }, + update: function () { + var data = this.data; + this.controllerIndex = data.hand === 'right' ? 0 : data.hand === 'left' ? 1 : 2; + }, + play: function () { + this.checkIfControllerPresent(); + this.addControllersUpdateListener(); + }, + pause: function () { + this.removeEventListeners(); + this.removeControllersUpdateListener(); + }, + bindMethods: function () { + this.onModelLoaded = bind(this.onModelLoaded, this); + this.onControllersUpdate = bind(this.onControllersUpdate, this); + this.checkIfControllerPresent = bind(this.checkIfControllerPresent, this); + this.removeControllersUpdateListener = bind(this.removeControllersUpdateListener, this); + this.onAxisMoved = bind(this.onAxisMoved, this); + }, + addEventListeners: function () { + var el = this.el; + el.addEventListener('buttonchanged', this.onButtonChanged); + el.addEventListener('buttondown', this.onButtonDown); + el.addEventListener('buttonup', this.onButtonUp); + el.addEventListener('touchstart', this.onButtonTouchStart); + el.addEventListener('touchend', this.onButtonTouchEnd); + el.addEventListener('axismove', this.onAxisMoved); + el.addEventListener('model-loaded', this.onModelLoaded); + this.controllerEventsActive = true; + }, + removeEventListeners: function () { + var el = this.el; + el.removeEventListener('buttonchanged', this.onButtonChanged); + el.removeEventListener('buttondown', this.onButtonDown); + el.removeEventListener('buttonup', this.onButtonUp); + el.removeEventListener('touchstart', this.onButtonTouchStart); + el.removeEventListener('touchend', this.onButtonTouchEnd); + el.removeEventListener('axismove', this.onAxisMoved); + el.removeEventListener('model-loaded', this.onModelLoaded); + this.controllerEventsActive = false; + }, + checkIfControllerPresent: function () { + var data = this.data; + checkControllerPresentAndSetup(this, GAMEPAD_ID, { + index: this.controllerIndex, + hand: data.hand + }); + }, + injectTrackedControls: function () { + var el = this.el; + var data = this.data; + el.setAttribute('tracked-controls', { + // TODO: verify expected behavior between reserved prefixes. + idPrefix: GAMEPAD_ID, + hand: data.hand, + controller: this.controllerIndex, + orientationOffset: data.orientationOffset + }); + + // Load model. + if (!this.data.model) { + return; + } + this.el.setAttribute('gltf-model', HP_MIXEDL_REALITY_MODEL_GLB_BASE_URL + this.data.hand + '.glb'); + }, + addControllersUpdateListener: function () { + this.el.sceneEl.addEventListener('controllersupdated', this.onControllersUpdate, false); + }, + removeControllersUpdateListener: function () { + this.el.sceneEl.removeEventListener('controllersupdated', this.onControllersUpdate, false); + }, + onControllersUpdate: function () { + // Note that due to gamepadconnected event propagation issues, we don't rely on events. + this.checkIfControllerPresent(); + }, + onButtonChanged: function (evt) { + var button = this.mapping[this.data.hand].buttons[evt.detail.id]; + var analogValue; + if (!button) { + return; + } + if (button === 'trigger') { + analogValue = evt.detail.state.value; + console.log('analog value of trigger press: ' + analogValue); + } + + // Pass along changed event with button state, using button mapping for convenience. + this.el.emit(button + 'changed', evt.detail.state); + }, + onModelLoaded: function (evt) { + var controllerObject3D = evt.detail.model; + if (!this.data.model) { + return; + } + controllerObject3D.position.copy(HP_MIXED_REALITY_POSITION_OFFSET); + controllerObject3D.rotation.copy(HP_MIXED_REALITY_ROTATION_OFFSET); + this.el.emit('controllermodelready', { + name: 'hp-mixed-reality-controls', + model: this.data.model, + rayOrigin: new THREE.Vector3(0, 0, 0) + }); + }, + onAxisMoved: function (evt) { + emitIfAxesChanged(this, this.mapping.axes, evt); + } +}); + +/***/ }), + +/***/ "./src/components/index.js": +/*!*********************************!*\ + !*** ./src/components/index.js ***! + \*********************************/ +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +__webpack_require__(/*! ./animation */ "./src/components/animation.js"); +__webpack_require__(/*! ./camera */ "./src/components/camera.js"); +__webpack_require__(/*! ./cursor */ "./src/components/cursor.js"); +__webpack_require__(/*! ./daydream-controls */ "./src/components/daydream-controls.js"); +__webpack_require__(/*! ./gearvr-controls */ "./src/components/gearvr-controls.js"); +__webpack_require__(/*! ./geometry */ "./src/components/geometry.js"); +__webpack_require__(/*! ./generic-tracked-controller-controls */ "./src/components/generic-tracked-controller-controls.js"); +__webpack_require__(/*! ./gltf-model */ "./src/components/gltf-model.js"); +__webpack_require__(/*! ./hand-tracking-controls */ "./src/components/hand-tracking-controls.js"); +__webpack_require__(/*! ./hand-controls */ "./src/components/hand-controls.js"); +__webpack_require__(/*! ./hide-on-enter-ar */ "./src/components/hide-on-enter-ar.js"); +__webpack_require__(/*! ./hp-mixed-reality-controls */ "./src/components/hp-mixed-reality-controls.js"); +__webpack_require__(/*! ./layer */ "./src/components/layer.js"); +__webpack_require__(/*! ./laser-controls */ "./src/components/laser-controls.js"); +__webpack_require__(/*! ./light */ "./src/components/light.js"); +__webpack_require__(/*! ./line */ "./src/components/line.js"); +__webpack_require__(/*! ./link */ "./src/components/link.js"); +__webpack_require__(/*! ./look-controls */ "./src/components/look-controls.js"); +__webpack_require__(/*! ./magicleap-controls */ "./src/components/magicleap-controls.js"); +__webpack_require__(/*! ./material */ "./src/components/material.js"); +__webpack_require__(/*! ./obj-model */ "./src/components/obj-model.js"); +__webpack_require__(/*! ./oculus-go-controls */ "./src/components/oculus-go-controls.js"); +__webpack_require__(/*! ./oculus-touch-controls */ "./src/components/oculus-touch-controls.js"); +__webpack_require__(/*! ./position */ "./src/components/position.js"); +__webpack_require__(/*! ./raycaster */ "./src/components/raycaster.js"); +__webpack_require__(/*! ./rotation */ "./src/components/rotation.js"); +__webpack_require__(/*! ./scale */ "./src/components/scale.js"); +__webpack_require__(/*! ./shadow */ "./src/components/shadow.js"); +__webpack_require__(/*! ./sound */ "./src/components/sound.js"); +__webpack_require__(/*! ./text */ "./src/components/text.js"); +__webpack_require__(/*! ./tracked-controls */ "./src/components/tracked-controls.js"); +__webpack_require__(/*! ./tracked-controls-webvr */ "./src/components/tracked-controls-webvr.js"); +__webpack_require__(/*! ./tracked-controls-webxr */ "./src/components/tracked-controls-webxr.js"); +__webpack_require__(/*! ./visible */ "./src/components/visible.js"); +__webpack_require__(/*! ./valve-index-controls */ "./src/components/valve-index-controls.js"); +__webpack_require__(/*! ./vive-controls */ "./src/components/vive-controls.js"); +__webpack_require__(/*! ./vive-focus-controls */ "./src/components/vive-focus-controls.js"); +__webpack_require__(/*! ./wasd-controls */ "./src/components/wasd-controls.js"); +__webpack_require__(/*! ./windows-motion-controls */ "./src/components/windows-motion-controls.js"); +__webpack_require__(/*! ./scene/ar-hit-test */ "./src/components/scene/ar-hit-test.js"); +__webpack_require__(/*! ./scene/background */ "./src/components/scene/background.js"); +__webpack_require__(/*! ./scene/debug */ "./src/components/scene/debug.js"); +__webpack_require__(/*! ./scene/device-orientation-permission-ui */ "./src/components/scene/device-orientation-permission-ui.js"); +__webpack_require__(/*! ./scene/embedded */ "./src/components/scene/embedded.js"); +__webpack_require__(/*! ./scene/inspector */ "./src/components/scene/inspector.js"); +__webpack_require__(/*! ./scene/fog */ "./src/components/scene/fog.js"); +__webpack_require__(/*! ./scene/keyboard-shortcuts */ "./src/components/scene/keyboard-shortcuts.js"); +__webpack_require__(/*! ./scene/pool */ "./src/components/scene/pool.js"); +__webpack_require__(/*! ./scene/reflection */ "./src/components/scene/reflection.js"); +__webpack_require__(/*! ./scene/screenshot */ "./src/components/scene/screenshot.js"); +__webpack_require__(/*! ./scene/stats */ "./src/components/scene/stats.js"); +__webpack_require__(/*! ./scene/vr-mode-ui */ "./src/components/scene/vr-mode-ui.js"); + +/***/ }), + +/***/ "./src/components/laser-controls.js": +/*!******************************************!*\ + !*** ./src/components/laser-controls.js ***! + \******************************************/ +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var utils = __webpack_require__(/*! ../utils/ */ "./src/utils/index.js"); +registerComponent('laser-controls', { + schema: { + hand: { + default: 'right' + }, + model: { + default: true + }, + defaultModelColor: { + type: 'color', + default: 'grey' + } + }, + init: function () { + var config = this.config; + var data = this.data; + var el = this.el; + var self = this; + var controlsConfiguration = { + hand: data.hand, + model: data.model + }; + + // Set all controller models. + el.setAttribute('daydream-controls', controlsConfiguration); + el.setAttribute('gearvr-controls', controlsConfiguration); + el.setAttribute('hp-mixed-reality-controls', controlsConfiguration); + el.setAttribute('magicleap-controls', controlsConfiguration); + el.setAttribute('oculus-go-controls', controlsConfiguration); + el.setAttribute('oculus-touch-controls', controlsConfiguration); + el.setAttribute('valve-index-controls', controlsConfiguration); + el.setAttribute('vive-controls', controlsConfiguration); + el.setAttribute('vive-focus-controls', controlsConfiguration); + el.setAttribute('windows-motion-controls', controlsConfiguration); + el.setAttribute('generic-tracked-controller-controls', { + hand: controlsConfiguration.hand + }); + + // Wait for controller to connect, or have a valid pointing pose, before creating ray + el.addEventListener('controllerconnected', createRay); + el.addEventListener('controllerdisconnected', hideRay); + el.addEventListener('controllermodelready', function (evt) { + createRay(evt); + self.modelReady = true; + }); + function createRay(evt) { + var controllerConfig = config[evt.detail.name]; + if (!controllerConfig) { + return; + } + + // Show the line unless a particular config opts to hide it, until a controllermodelready + // event comes through. + var raycasterConfig = utils.extend({ + showLine: true + }, controllerConfig.raycaster || {}); + + // The controllermodelready event contains a rayOrigin that takes into account + // offsets specific to the loaded model. + if (evt.detail.rayOrigin) { + raycasterConfig.origin = evt.detail.rayOrigin.origin; + raycasterConfig.direction = evt.detail.rayOrigin.direction; + raycasterConfig.showLine = true; + } + + // Only apply a default raycaster if it does not yet exist. This prevents it overwriting + // config applied from a controllermodelready event. + if (evt.detail.rayOrigin || !self.modelReady) { + el.setAttribute('raycaster', raycasterConfig); + } else { + el.setAttribute('raycaster', 'showLine', true); + } + el.setAttribute('cursor', utils.extend({ + fuse: false + }, controllerConfig.cursor)); + } + function hideRay() { + el.setAttribute('raycaster', 'showLine', false); + } + }, + config: { + 'daydream-controls': { + cursor: { + downEvents: ['trackpaddown', 'triggerdown'], + upEvents: ['trackpadup', 'triggerup'] + } + }, + 'gearvr-controls': { + cursor: { + downEvents: ['triggerdown'], + upEvents: ['triggerup'] + }, + raycaster: { + origin: { + x: 0, + y: 0.0010, + z: 0 + } + } + }, + 'generic-tracked-controller-controls': { + cursor: { + downEvents: ['triggerdown'], + upEvents: ['triggerup'] + } + }, + 'hp-mixed-reality-controls': { + cursor: { + downEvents: ['triggerdown'], + upEvents: ['triggerup'] + }, + raycaster: { + origin: { + x: 0, + y: 0, + z: 0 + } + } + }, + 'magicleap-controls': { + cursor: { + downEvents: ['trackpaddown', 'triggerdown'], + upEvents: ['trackpadup', 'triggerup'] + } + }, + 'oculus-go-controls': { + cursor: { + downEvents: ['triggerdown'], + upEvents: ['triggerup'] + }, + raycaster: { + origin: { + x: 0, + y: 0.0005, + z: 0 + } + } + }, + 'oculus-touch-controls': { + cursor: { + downEvents: ['triggerdown'], + upEvents: ['triggerup'] + }, + raycaster: { + origin: { + x: 0, + y: 0, + z: 0 + } + } + }, + 'valve-index-controls': { + cursor: { + downEvents: ['triggerdown'], + upEvents: ['triggerup'] + } + }, + 'vive-controls': { + cursor: { + downEvents: ['triggerdown'], + upEvents: ['triggerup'] + } + }, + 'vive-focus-controls': { + cursor: { + downEvents: ['trackpaddown', 'triggerdown'], + upEvents: ['trackpadup', 'triggerup'] + } + }, + 'windows-motion-controls': { + cursor: { + downEvents: ['triggerdown'], + upEvents: ['triggerup'] + }, + raycaster: { + showLine: false + } + } + } +}); + +/***/ }), + +/***/ "./src/components/layer.js": +/*!*********************************!*\ + !*** ./src/components/layer.js ***! + \*********************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/* global THREE, XRRigidTransform, XRWebGLBinding */ +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var utils = __webpack_require__(/*! ../utils/ */ "./src/utils/index.js"); +var warn = utils.debug('components:layer:warn'); +module.exports.Component = registerComponent('layer', { + schema: { + type: { + default: 'quad', + oneOf: ['quad', 'monocubemap', 'stereocubemap'] + }, + src: { + type: 'map' + }, + rotateCubemap: { + default: false + }, + width: { + default: 0 + }, + height: { + default: 0 + } + }, + init: function () { + var gl = this.el.sceneEl.renderer.getContext(); + this.quaternion = new THREE.Quaternion(); + this.position = new THREE.Vector3(); + this.bindMethods(); + this.needsRedraw = false; + this.frameBuffer = gl.createFramebuffer(); + var requiredFeatures = this.el.sceneEl.getAttribute('webxr').requiredFeatures; + requiredFeatures.push('layers'); + this.el.sceneEl.getAttribute('webxr', 'requiredFeatures', requiredFeatures); + this.el.sceneEl.addEventListener('enter-vr', this.onEnterVR); + this.el.sceneEl.addEventListener('exit-vr', this.onExitVR); + }, + bindMethods: function () { + this.onRequestedReferenceSpace = this.onRequestedReferenceSpace.bind(this); + this.onEnterVR = this.onEnterVR.bind(this); + this.onExitVR = this.onExitVR.bind(this); + }, + update: function (oldData) { + if (this.data.src !== oldData.src) { + this.updateSrc(); + } + }, + updateSrc: function () { + var type = this.data.type; + this.texture = undefined; + if (type === 'quad') { + this.loadQuadImage(); + return; + } + if (type === 'monocubemap' || type === 'stereocubemap') { + this.loadCubeMapImages(); + return; + } + }, + loadCubeMapImages: function () { + var glayer; + var xrGLFactory = this.xrGLFactory; + var frame = this.el.sceneEl.frame; + var src = this.data.src; + var type = this.data.type; + this.visibilityChanged = false; + if (!this.layer) { + return; + } + if (type !== 'monocubemap' && type !== 'stereocubemap') { + return; + } + if (!src.complete) { + this.pendingCubeMapUpdate = true; + } else { + this.pendingCubeMapUpdate = false; + } + if (!this.loadingScreen) { + this.loadingScreen = true; + } else { + this.loadingScreen = false; + } + if (type === 'monocubemap') { + glayer = xrGLFactory.getSubImage(this.layer, frame); + this.loadCubeMapImage(glayer.colorTexture, src, 0); + } else { + glayer = xrGLFactory.getSubImage(this.layer, frame, 'left'); + this.loadCubeMapImage(glayer.colorTexture, src, 0); + glayer = xrGLFactory.getSubImage(this.layer, frame, 'right'); + this.loadCubeMapImage(glayer.colorTexture, src, 6); + } + }, + loadQuadImage: function () { + var src = this.data.src; + var self = this; + this.el.sceneEl.systems.material.loadTexture(src, { + src: src + }, function textureLoaded(texture) { + self.el.sceneEl.renderer.initTexture(texture); + self.texture = texture; + if (src.tagName === 'VIDEO') { + setTimeout(function () { + self.textureIsVideo = true; + }, 1000); + } + if (self.layer) { + self.layer.height = self.data.height / 2 || self.texture.image.height / 1000; + self.layer.width = self.data.width / 2 || self.texture.image.width / 1000; + self.needsRedraw = true; + } + self.updateQuadPanel(); + }); + }, + preGenerateCubeMapTextures: function (src, callback) { + if (this.data.type === 'monocubemap') { + this.generateCubeMapTextures(src, 0, callback); + } else { + this.generateCubeMapTextures(src, 0, callback); + this.generateCubeMapTextures(src, 6, callback); + } + }, + generateCubeMapTextures: function (src, faceOffset, callback) { + var data = this.data; + var cubeFaceSize = this.cubeFaceSize; + var textureSourceCubeFaceSize = Math.min(src.width, src.height); + var cubefaceTextures = []; + var imgTmp0; + var imgTmp2; + for (var i = 0; i < 6; i++) { + var tempCanvas = document.createElement('CANVAS'); + tempCanvas.width = tempCanvas.height = cubeFaceSize; + var tempCanvasContext = tempCanvas.getContext('2d'); + if (data.rotateCubemap) { + if (i === 2 || i === 3) { + tempCanvasContext.save(); + tempCanvasContext.translate(cubeFaceSize, cubeFaceSize); + tempCanvasContext.rotate(Math.PI); + } + } + + // Note that this call to drawImage will not only copy the bytes to the + // canvas but also could resized the image if our cube face size is + // smaller than the source image due to GL max texture size. + tempCanvasContext.drawImage(src, (i + faceOffset) * textureSourceCubeFaceSize, + // top left x coord in source + 0, + // top left y coord in source + textureSourceCubeFaceSize, + // x pixel count from source + textureSourceCubeFaceSize, + // y pixel count from source + 0, + // dest x offset in the canvas + 0, + // dest y offset in the canvas + cubeFaceSize, + // x pixel count in dest + cubeFaceSize // y pixel count in dest + ); + + tempCanvasContext.restore(); + if (callback) { + callback(); + } + cubefaceTextures.push(tempCanvas); + } + if (data.rotateCubemap) { + imgTmp0 = cubefaceTextures[0]; + imgTmp2 = cubefaceTextures[1]; + cubefaceTextures[0] = imgTmp2; + cubefaceTextures[1] = imgTmp0; + imgTmp0 = cubefaceTextures[4]; + imgTmp2 = cubefaceTextures[5]; + cubefaceTextures[4] = imgTmp2; + cubefaceTextures[5] = imgTmp0; + } + if (callback) { + callback(); + } + return cubefaceTextures; + }, + loadCubeMapImage: function (layerColorTexture, src, faceOffset) { + var gl = this.el.sceneEl.renderer.getContext(); + var cubefaceTextures; + + // dont flip the pixels as we load them into the texture buffer. + // TEXTURE_CUBE_MAP expects the Y to be flipped for the faces and it already + // is flipped in our texture image. + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + gl.bindTexture(gl.TEXTURE_CUBE_MAP, layerColorTexture); + if (!src.complete || this.loadingScreen) { + cubefaceTextures = this.loadingScreenImages; + } else { + cubefaceTextures = this.generateCubeMapTextures(src, faceOffset); + } + var errorCode = 0; + cubefaceTextures.forEach(function (canvas, i) { + gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, canvas); + errorCode = gl.getError(); + }); + if (errorCode !== 0) { + console.log('renderingError, WebGL Error Code: ' + errorCode); + } + gl.bindTexture(gl.TEXTURE_CUBE_MAP, null); + }, + tick: function () { + if (!this.el.sceneEl.xrSession) { + return; + } + if (!this.layer && this.el.sceneEl.is('vr-mode')) { + this.initLayer(); + } + this.updateTransform(); + if (this.data.src.complete && (this.pendingCubeMapUpdate || this.loadingScreen || this.visibilityChanged)) { + this.loadCubeMapImages(); + } + if (!this.needsRedraw && !this.layer.needsRedraw && !this.textureIsVideo) { + return; + } + if (this.data.type === 'quad') { + this.draw(); + } + this.needsRedraw = false; + }, + initLayer: function () { + var self = this; + var type = this.data.type; + this.el.sceneEl.xrSession.onvisibilitychange = function (evt) { + self.visibilityChanged = evt.session.visibilityState !== 'hidden'; + }; + if (type === 'quad') { + this.initQuadLayer(); + return; + } + if (type === 'monocubemap' || type === 'stereocubemap') { + this.initCubeMapLayer(); + return; + } + }, + initQuadLayer: function () { + var sceneEl = this.el.sceneEl; + var gl = sceneEl.renderer.getContext(); + var xrGLFactory = this.xrGLFactory = new XRWebGLBinding(sceneEl.xrSession, gl); + if (!this.texture) { + return; + } + this.layer = xrGLFactory.createQuadLayer({ + space: this.referenceSpace, + viewPixelHeight: 2048, + viewPixelWidth: 2048, + height: this.data.height / 2 || this.texture.image.height / 1000, + width: this.data.width / 2 || this.texture.image.width / 1000 + }); + this.initLoadingScreenImages(); + sceneEl.renderer.xr.addLayer(this.layer); + }, + initCubeMapLayer: function () { + var src = this.data.src; + var sceneEl = this.el.sceneEl; + var gl = sceneEl.renderer.getContext(); + var glSizeLimit = gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE); + var cubeFaceSize = this.cubeFaceSize = Math.min(glSizeLimit, Math.min(src.width, src.height)); + var xrGLFactory = this.xrGLFactory = new XRWebGLBinding(sceneEl.xrSession, gl); + this.layer = xrGLFactory.createCubeLayer({ + space: this.referenceSpace, + viewPixelWidth: cubeFaceSize, + viewPixelHeight: cubeFaceSize, + layout: this.data.type === 'monocubemap' ? 'mono' : 'stereo', + isStatic: false + }); + this.initLoadingScreenImages(); + this.loadCubeMapImages(); + sceneEl.renderer.xr.addLayer(this.layer); + }, + initLoadingScreenImages: function () { + var cubeFaceSize = this.cubeFaceSize; + var loadingScreenImages = this.loadingScreenImages = []; + for (var i = 0; i < 6; i++) { + var tempCanvas = document.createElement('CANVAS'); + tempCanvas.width = tempCanvas.height = cubeFaceSize; + var tempCanvasContext = tempCanvas.getContext('2d'); + tempCanvas.width = tempCanvas.height = cubeFaceSize; + tempCanvasContext.fillStyle = 'black'; + tempCanvasContext.fillRect(0, 0, cubeFaceSize, cubeFaceSize); + if (i !== 2 && i !== 3) { + tempCanvasContext.translate(cubeFaceSize, 0); + tempCanvasContext.scale(-1, 1); + tempCanvasContext.fillStyle = 'white'; + tempCanvasContext.font = '30px Arial'; + tempCanvasContext.fillText('Loading', cubeFaceSize / 2, cubeFaceSize / 2); + } + loadingScreenImages.push(tempCanvas); + } + }, + destroyLayer: function () { + if (!this.layer) { + return; + } + this.el.sceneEl.renderer.xr.removeLayer(this.layer); + this.layer.destroy(); + this.layer = undefined; + }, + toggleCompositorLayer: function () { + this.enableCompositorLayer(!this.layerEnabled); + }, + enableCompositorLayer: function (enable) { + this.layerEnabled = enable; + this.quadPanelEl.object3D.visible = !this.layerEnabled; + }, + updateQuadPanel: function () { + var quadPanelEl = this.quadPanelEl; + if (!this.quadPanelEl) { + quadPanelEl = this.quadPanelEl = document.createElement('a-entity'); + this.el.appendChild(quadPanelEl); + } + quadPanelEl.setAttribute('material', { + shader: 'flat', + src: this.data.src, + transparent: true + }); + quadPanelEl.setAttribute('geometry', { + primitive: 'plane', + height: this.data.height || this.texture.image.height / 1000, + width: this.data.width || this.texture.image.height / 1000 + }); + }, + draw: function () { + var sceneEl = this.el.sceneEl; + var gl = this.el.sceneEl.renderer.getContext(); + var glayer = this.xrGLFactory.getSubImage(this.layer, sceneEl.frame); + var texture = sceneEl.renderer.properties.get(this.texture).__webglTexture; + var previousFrameBuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING); + gl.viewport(glayer.viewport.x, glayer.viewport.y, glayer.viewport.width, glayer.viewport.height); + gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, glayer.colorTexture, 0); + blitTexture(gl, texture, glayer, this.data.src); + gl.bindFramebuffer(gl.FRAMEBUFFER, previousFrameBuffer); + }, + updateTransform: function () { + var el = this.el; + var position = this.position; + var quaternion = this.quaternion; + el.object3D.updateMatrixWorld(); + position.setFromMatrixPosition(el.object3D.matrixWorld); + quaternion.setFromRotationMatrix(el.object3D.matrixWorld); + if (!this.layerEnabled) { + position.set(0, 0, 100000000); + } + this.layer.transform = new XRRigidTransform(position, quaternion); + }, + onEnterVR: function () { + var sceneEl = this.el.sceneEl; + var xrSession = sceneEl.xrSession; + if (!sceneEl.hasWebXR || !XRWebGLBinding || !xrSession) { + warn('The layer component requires WebXR and the layers API enabled'); + return; + } + xrSession.requestReferenceSpace('local-floor').then(this.onRequestedReferenceSpace); + this.needsRedraw = true; + this.layerEnabled = true; + if (this.quadPanelEl) { + this.quadPanelEl.object3D.visible = false; + } + if (this.data.src.play) { + this.data.src.play(); + } + }, + onExitVR: function () { + if (this.quadPanelEl) { + this.quadPanelEl.object3D.visible = true; + } + this.destroyLayer(); + }, + onRequestedReferenceSpace: function (referenceSpace) { + this.referenceSpace = referenceSpace; + } +}); +function blitTexture(gl, texture, subImage, textureEl) { + var xrReadFramebuffer = gl.createFramebuffer(); + let x1offset = subImage.viewport.x; + let y1offset = subImage.viewport.y; + let x2offset = subImage.viewport.x + subImage.viewport.width; + let y2offset = subImage.viewport.y + subImage.viewport.height; + + // Update video texture. + if (textureEl.tagName === 'VIDEO') { + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, textureEl.width, textureEl.height, gl.RGB, gl.UNSIGNED_BYTE, textureEl); + } + + // Bind texture to read framebuffer. + gl.bindFramebuffer(gl.READ_FRAMEBUFFER, xrReadFramebuffer); + gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); + + // Blit into layer buffer. + gl.readBuffer(gl.COLOR_ATTACHMENT0); + gl.blitFramebuffer(0, 0, textureEl.width, textureEl.height, x1offset, y1offset, x2offset, y2offset, gl.COLOR_BUFFER_BIT, gl.NEAREST); + gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null); + gl.deleteFramebuffer(xrReadFramebuffer); +} + +/***/ }), + +/***/ "./src/components/light.js": +/*!*********************************!*\ + !*** ./src/components/light.js ***! + \*********************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var bind = __webpack_require__(/*! ../utils/bind */ "./src/utils/bind.js"); +var utils = __webpack_require__(/*! ../utils */ "./src/utils/index.js"); +var diff = utils.diff; +var debug = __webpack_require__(/*! ../utils/debug */ "./src/utils/debug.js"); +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var THREE = __webpack_require__(/*! ../lib/three */ "./src/lib/three.js"); +var mathUtils = __webpack_require__(/*! ../utils/math */ "./src/utils/math.js"); +var degToRad = THREE.MathUtils.degToRad; +var warn = debug('components:light:warn'); +var CubeLoader = new THREE.CubeTextureLoader(); +var probeCache = {}; + +/** + * Light component. + */ +module.exports.Component = registerComponent('light', { + schema: { + angle: { + default: 60, + if: { + type: ['spot'] + } + }, + color: { + type: 'color', + if: { + type: ['ambient', 'directional', 'hemisphere', 'point', 'spot'] + } + }, + envMap: { + default: '', + if: { + type: ['probe'] + } + }, + groundColor: { + type: 'color', + if: { + type: ['hemisphere'] + } + }, + decay: { + default: 1, + if: { + type: ['point', 'spot'] + } + }, + distance: { + default: 0.0, + min: 0, + if: { + type: ['point', 'spot'] + } + }, + intensity: { + default: 1.0, + min: 0, + if: { + type: ['ambient', 'directional', 'hemisphere', 'point', 'spot', 'probe'] + } + }, + penumbra: { + default: 0, + min: 0, + max: 1, + if: { + type: ['spot'] + } + }, + type: { + default: 'directional', + oneOf: ['ambient', 'directional', 'hemisphere', 'point', 'spot', 'probe'], + schemaChange: true + }, + target: { + type: 'selector', + if: { + type: ['spot', 'directional'] + } + }, + // Shadows. + castShadow: { + default: false, + if: { + type: ['point', 'spot', 'directional'] + } + }, + shadowBias: { + default: 0, + if: { + castShadow: true + } + }, + shadowCameraFar: { + default: 500, + if: { + castShadow: true + } + }, + shadowCameraFov: { + default: 90, + if: { + castShadow: true + } + }, + shadowCameraNear: { + default: 0.5, + if: { + castShadow: true + } + }, + shadowCameraTop: { + default: 5, + if: { + castShadow: true + } + }, + shadowCameraRight: { + default: 5, + if: { + castShadow: true + } + }, + shadowCameraBottom: { + default: -5, + if: { + castShadow: true + } + }, + shadowCameraLeft: { + default: -5, + if: { + castShadow: true + } + }, + shadowCameraVisible: { + default: false, + if: { + castShadow: true + } + }, + shadowCameraAutomatic: { + default: '', + if: { + type: ['directional'] + } + }, + shadowMapHeight: { + default: 512, + if: { + castShadow: true + } + }, + shadowMapWidth: { + default: 512, + if: { + castShadow: true + } + }, + shadowRadius: { + default: 1, + if: { + castShadow: true + } + } + }, + /** + * Notifies scene a light has been added to remove default lighting. + */ + init: function () { + var el = this.el; + this.light = null; + this.defaultTarget = null; + this.rendererSystem = this.el.sceneEl.systems.renderer; + this.system.registerLight(el); + }, + /** + * (Re)create or update light. + */ + update: function (oldData) { + var data = this.data; + var diffData = diff(data, oldData); + var light = this.light; + var rendererSystem = this.rendererSystem; + var self = this; + + // Existing light. + if (light && !('type' in diffData)) { + var shadowsLoaded = false; + // Light type has not changed. Update light. + Object.keys(diffData).forEach(function (key) { + var value = data[key]; + switch (key) { + case 'color': + { + light.color.set(value); + rendererSystem.applyColorCorrection(light.color); + break; + } + case 'groundColor': + { + light.groundColor.set(value); + rendererSystem.applyColorCorrection(light.groundColor); + break; + } + case 'angle': + { + light.angle = degToRad(value); + break; + } + case 'target': + { + // Reset target if selector is null. + if (value === null) { + if (data.type === 'spot' || data.type === 'directional') { + light.target = self.defaultTarget; + } + } else { + // Target specified, set target to entity's `object3D` when it is loaded. + if (value.hasLoaded) { + self.onSetTarget(value, light); + } else { + value.addEventListener('loaded', bind(self.onSetTarget, self, value, light)); + } + } + break; + } + case 'envMap': + self.updateProbeMap(data, light); + break; + case 'castShadow': + case 'shadowBias': + case 'shadowCameraFar': + case 'shadowCameraFov': + case 'shadowCameraNear': + case 'shadowCameraTop': + case 'shadowCameraRight': + case 'shadowCameraBottom': + case 'shadowCameraLeft': + case 'shadowCameraVisible': + case 'shadowMapHeight': + case 'shadowMapWidth': + case 'shadowRadius': + if (!shadowsLoaded) { + self.updateShadow(); + shadowsLoaded = true; + } + break; + case 'shadowCameraAutomatic': + if (data.shadowCameraAutomatic) { + self.shadowCameraAutomaticEls = Array.from(document.querySelectorAll(data.shadowCameraAutomatic)); + } else { + self.shadowCameraAutomaticEls = []; + } + break; + default: + { + light[key] = value; + } + } + }); + return; + } + + // No light yet or light type has changed. Create and add light. + this.setLight(this.data); + this.updateShadow(); + }, + tick: function () { + var bbox = new THREE.Box3(); + var normal = new THREE.Vector3(); + var cameraWorldPosition = new THREE.Vector3(); + var tempMat = new THREE.Matrix4(); + var sphere = new THREE.Sphere(); + var tempVector = new THREE.Vector3(); + return function () { + if (!(this.data.type === 'directional' && this.light.shadow && this.light.shadow.camera instanceof THREE.OrthographicCamera && this.shadowCameraAutomaticEls.length)) return; + var camera = this.light.shadow.camera; + camera.getWorldDirection(normal); + camera.getWorldPosition(cameraWorldPosition); + tempMat.copy(camera.matrixWorld); + tempMat.invert(); + camera.near = 1; + camera.left = 100000; + camera.right = -100000; + camera.top = -100000; + camera.bottom = 100000; + this.shadowCameraAutomaticEls.forEach(function (el) { + bbox.setFromObject(el.object3D); + bbox.getBoundingSphere(sphere); + var distanceToPlane = mathUtils.distanceOfPointFromPlane(cameraWorldPosition, normal, sphere.center); + var pointOnCameraPlane = mathUtils.nearestPointInPlane(cameraWorldPosition, normal, sphere.center, tempVector); + var pointInXYPlane = pointOnCameraPlane.applyMatrix4(tempMat); + camera.near = Math.min(-distanceToPlane - sphere.radius - 1, camera.near); + camera.left = Math.min(-sphere.radius + pointInXYPlane.x, camera.left); + camera.right = Math.max(sphere.radius + pointInXYPlane.x, camera.right); + camera.top = Math.max(sphere.radius + pointInXYPlane.y, camera.top); + camera.bottom = Math.min(-sphere.radius + pointInXYPlane.y, camera.bottom); + }); + camera.updateProjectionMatrix(); + }; + }(), + setLight: function (data) { + var el = this.el; + var newLight = this.getLight(data); + if (newLight) { + if (this.light) { + el.removeObject3D('light'); + } + this.light = newLight; + this.light.el = el; + el.setObject3D('light', this.light); + + // HACK solution for issue #1624 + if (data.type === 'spot' || data.type === 'directional' || data.type === 'hemisphere') { + el.getObject3D('light').translateY(-1); + } + + // set and position default lighttarget as a child to enable spotlight orientation + if (data.type === 'spot') { + el.setObject3D('light-target', this.defaultTarget); + el.getObject3D('light-target').position.set(0, 0, -1); + } + if (data.shadowCameraAutomatic) { + this.shadowCameraAutomaticEls = Array.from(document.querySelectorAll(data.shadowCameraAutomatic)); + } else { + this.shadowCameraAutomaticEls = []; + } + } + }, + /** + * Updates shadow-related properties on the current light. + */ + updateShadow: function () { + var el = this.el; + var data = this.data; + var light = this.light; + light.castShadow = data.castShadow; + + // Shadow camera helper. + var cameraHelper = el.getObject3D('cameraHelper'); + if (data.shadowCameraVisible && !cameraHelper) { + el.setObject3D('cameraHelper', new THREE.CameraHelper(light.shadow.camera)); + } else if (!data.shadowCameraVisible && cameraHelper) { + el.removeObject3D('cameraHelper'); + } + if (!data.castShadow) { + return light; + } + + // Shadow appearance. + light.shadow.bias = data.shadowBias; + light.shadow.radius = data.shadowRadius; + light.shadow.mapSize.height = data.shadowMapHeight; + light.shadow.mapSize.width = data.shadowMapWidth; + + // Shadow camera. + light.shadow.camera.near = data.shadowCameraNear; + light.shadow.camera.far = data.shadowCameraFar; + if (light.shadow.camera instanceof THREE.OrthographicCamera) { + light.shadow.camera.top = data.shadowCameraTop; + light.shadow.camera.right = data.shadowCameraRight; + light.shadow.camera.bottom = data.shadowCameraBottom; + light.shadow.camera.left = data.shadowCameraLeft; + } else { + light.shadow.camera.fov = data.shadowCameraFov; + } + light.shadow.camera.updateProjectionMatrix(); + if (cameraHelper) { + cameraHelper.update(); + } + }, + /** + * Creates a new three.js light object given data object defining the light. + * + * @param {object} data + */ + getLight: function (data) { + var angle = data.angle; + var color = new THREE.Color(data.color); + this.rendererSystem.applyColorCorrection(color); + color = color.getHex(); + var decay = data.decay; + var distance = data.distance; + var groundColor = new THREE.Color(data.groundColor); + this.rendererSystem.applyColorCorrection(groundColor); + groundColor = groundColor.getHex(); + var intensity = data.intensity; + var type = data.type; + var target = data.target; + var light = null; + switch (type.toLowerCase()) { + case 'ambient': + { + return new THREE.AmbientLight(color, intensity); + } + case 'directional': + { + light = new THREE.DirectionalLight(color, intensity); + this.defaultTarget = light.target; + if (target) { + if (target.hasLoaded) { + this.onSetTarget(target, light); + } else { + target.addEventListener('loaded', bind(this.onSetTarget, this, target, light)); + } + } + return light; + } + case 'hemisphere': + { + return new THREE.HemisphereLight(color, groundColor, intensity); + } + case 'point': + { + return new THREE.PointLight(color, intensity, distance, decay); + } + case 'spot': + { + light = new THREE.SpotLight(color, intensity, distance, degToRad(angle), data.penumbra, decay); + this.defaultTarget = light.target; + if (target) { + if (target.hasLoaded) { + this.onSetTarget(target, light); + } else { + target.addEventListener('loaded', bind(this.onSetTarget, this, target, light)); + } + } + return light; + } + case 'probe': + { + light = new THREE.LightProbe(); + this.updateProbeMap(data, light); + return light; + } + default: + { + warn('%s is not a valid light type. ' + 'Choose from ambient, directional, hemisphere, point, spot.', type); + } + } + }, + /** + * Generate the spherical harmonics for the LightProbe from a cube map + */ + updateProbeMap: function (data, light) { + if (!data.envMap) { + // reset parameters if no map + light.copy(new THREE.LightProbe()); + } + if (probeCache[data.envMap] instanceof window.Promise) { + probeCache[data.envMap].then(function (tempLightProbe) { + light.copy(tempLightProbe); + }); + } + if (probeCache[data.envMap] instanceof THREE.LightProbe) { + light.copy(probeCache[data.envMap]); + } + probeCache[data.envMap] = new window.Promise(function (resolve) { + utils.srcLoader.validateCubemapSrc(data.envMap, function loadEnvMap(urls) { + CubeLoader.load(urls, function (cube) { + var tempLightProbe = THREE.LightProbeGenerator.fromCubeTexture(cube); + probeCache[data.envMap] = tempLightProbe; + light.copy(tempLightProbe); + }); + }); + }); + }, + onSetTarget: function (targetEl, light) { + light.target = targetEl.object3D; + }, + /** + * Remove light on remove (callback). + */ + remove: function () { + var el = this.el; + el.removeObject3D('light'); + if (el.getObject3D('cameraHelper')) { + el.removeObject3D('cameraHelper'); + } + } +}); + +/***/ }), + +/***/ "./src/components/line.js": +/*!********************************!*\ + !*** ./src/components/line.js ***! + \********************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/* global THREE */ +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +module.exports.Component = registerComponent('line', { + schema: { + start: { + type: 'vec3', + default: { + x: 0, + y: 0, + z: 0 + } + }, + end: { + type: 'vec3', + default: { + x: 0, + y: 0, + z: 0 + } + }, + color: { + type: 'color', + default: '#74BEC1' + }, + opacity: { + type: 'number', + default: 1 + }, + visible: { + default: true + } + }, + multiple: true, + init: function () { + var data = this.data; + var geometry; + var material; + this.rendererSystem = this.el.sceneEl.systems.renderer; + material = this.material = new THREE.LineBasicMaterial({ + color: data.color, + opacity: data.opacity, + transparent: data.opacity < 1, + visible: data.visible + }); + geometry = this.geometry = new THREE.BufferGeometry(); + geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(2 * 3), 3)); + this.rendererSystem.applyColorCorrection(material.color); + this.line = new THREE.Line(geometry, material); + this.el.setObject3D(this.attrName, this.line); + }, + update: function (oldData) { + var data = this.data; + var geometry = this.geometry; + var geoNeedsUpdate = false; + var material = this.material; + var positionArray = geometry.attributes.position.array; + + // Update geometry. + if (!isEqualVec3(data.start, oldData.start)) { + positionArray[0] = data.start.x; + positionArray[1] = data.start.y; + positionArray[2] = data.start.z; + geoNeedsUpdate = true; + } + if (!isEqualVec3(data.end, oldData.end)) { + positionArray[3] = data.end.x; + positionArray[4] = data.end.y; + positionArray[5] = data.end.z; + geoNeedsUpdate = true; + } + if (geoNeedsUpdate) { + geometry.attributes.position.needsUpdate = true; + geometry.computeBoundingSphere(); + } + material.color.setStyle(data.color); + this.rendererSystem.applyColorCorrection(material.color); + material.opacity = data.opacity; + material.transparent = data.opacity < 1; + material.visible = data.visible; + }, + remove: function () { + this.el.removeObject3D(this.attrName, this.line); + } +}); +function isEqualVec3(a, b) { + if (!a || !b) { + return false; + } + return a.x === b.x && a.y === b.y && a.z === b.z; +} + +/***/ }), + +/***/ "./src/components/link.js": +/*!********************************!*\ + !*** ./src/components/link.js ***! + \********************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var registerShader = (__webpack_require__(/*! ../core/shader */ "./src/core/shader.js").registerShader); +var THREE = __webpack_require__(/*! ../lib/three */ "./src/lib/three.js"); + +/** + * Link component. Connect experiences and traverse between them in VR + * + * @member {object} hiddenEls - Store the hidden elements during peek mode. + */ +module.exports.Component = registerComponent('link', { + schema: { + backgroundColor: { + default: 'red', + type: 'color' + }, + borderColor: { + default: 'white', + type: 'color' + }, + highlighted: { + default: false + }, + highlightedColor: { + default: '#24CAFF', + type: 'color' + }, + href: { + default: '' + }, + image: { + type: 'asset' + }, + on: { + default: 'click' + }, + peekMode: { + default: false + }, + title: { + default: '' + }, + titleColor: { + default: 'white', + type: 'color' + }, + visualAspectEnabled: { + default: false + } + }, + init: function () { + this.navigate = this.navigate.bind(this); + this.previousQuaternion = undefined; + this.quaternionClone = new THREE.Quaternion(); + // Store hidden elements during peek mode so we can show them again later. + this.hiddenEls = []; + }, + update: function (oldData) { + var data = this.data; + var el = this.el; + var backgroundColor; + var strokeColor; + if (!data.visualAspectEnabled) { + return; + } + this.initVisualAspect(); + backgroundColor = data.highlighted ? data.highlightedColor : data.backgroundColor; + strokeColor = data.highlighted ? data.highlightedColor : data.borderColor; + el.setAttribute('material', 'backgroundColor', backgroundColor); + el.setAttribute('material', 'strokeColor', strokeColor); + if (data.on !== oldData.on) { + this.updateEventListener(); + } + if (oldData.peekMode !== undefined && data.peekMode !== oldData.peekMode) { + this.updatePeekMode(); + } + if (!data.image || oldData.image === data.image) { + return; + } + el.setAttribute('material', 'pano', typeof data.image === 'string' ? data.image : data.image.src); + }, + /* + * Toggle all elements and full 360 preview of the linked page. + */ + updatePeekMode: function () { + var el = this.el; + var sphereEl = this.sphereEl; + if (this.data.peekMode) { + this.hideAll(); + el.getObject3D('mesh').visible = false; + sphereEl.setAttribute('visible', true); + } else { + this.showAll(); + el.getObject3D('mesh').visible = true; + sphereEl.setAttribute('visible', false); + } + }, + play: function () { + this.updateEventListener(); + }, + pause: function () { + this.removeEventListener(); + }, + updateEventListener: function () { + var el = this.el; + if (!el.isPlaying) { + return; + } + this.removeEventListener(); + el.addEventListener(this.data.on, this.navigate); + }, + removeEventListener: function () { + var on = this.data.on; + if (!on) { + return; + } + this.el.removeEventListener(on, this.navigate); + }, + initVisualAspect: function () { + var el = this.el; + var semiSphereEl; + var sphereEl; + var textEl; + if (!this.data.visualAspectEnabled || this.visualAspectInitialized) { + return; + } + textEl = this.textEl = this.textEl || document.createElement('a-entity'); + sphereEl = this.sphereEl = this.sphereEl || document.createElement('a-entity'); + semiSphereEl = this.semiSphereEl = this.semiSphereEl || document.createElement('a-entity'); + + // Set portal. + el.setAttribute('geometry', { + primitive: 'circle', + radius: 1.0, + segments: 64 + }); + el.setAttribute('material', { + shader: 'portal', + pano: this.data.image, + side: 'double' + }); + + // Set text that displays the link title and URL. + textEl.setAttribute('text', { + color: this.data.titleColor, + align: 'center', + font: 'kelsonsans', + value: this.data.title || this.data.href, + width: 4 + }); + textEl.setAttribute('position', '0 1.5 0'); + el.appendChild(textEl); + + // Set sphere rendered when camera is close to portal to allow user to peek inside. + semiSphereEl.setAttribute('geometry', { + primitive: 'sphere', + radius: 1.0, + phiStart: 0, + segmentsWidth: 64, + segmentsHeight: 64, + phiLength: 180, + thetaStart: 0, + thetaLength: 360 + }); + semiSphereEl.setAttribute('material', { + shader: 'portal', + borderEnabled: 0.0, + pano: this.data.image, + side: 'back' + }); + semiSphereEl.setAttribute('rotation', '0 180 0'); + semiSphereEl.setAttribute('position', '0 0 0'); + semiSphereEl.setAttribute('visible', false); + el.appendChild(semiSphereEl); + + // Set sphere rendered when camera is close to portal to allow user to peek inside. + sphereEl.setAttribute('geometry', { + primitive: 'sphere', + radius: 10, + segmentsWidth: 64, + segmentsHeight: 64 + }); + sphereEl.setAttribute('material', { + shader: 'portal', + borderEnabled: 0.0, + pano: this.data.image, + side: 'back' + }); + sphereEl.setAttribute('visible', false); + el.appendChild(sphereEl); + this.visualAspectInitialized = true; + }, + navigate: function () { + window.location = this.data.href; + }, + /** + * 1. Swap plane that represents portal with sphere with a hole when the camera is close + * so user can peek inside portal. Sphere is rendered on oposite side of portal + * from where user enters. + * 2. Place the url/title above or inside portal depending on distance to camera. + * 3. Face portal to camera when far away from user. + */ + tick: function () { + var cameraWorldPosition = new THREE.Vector3(); + var elWorldPosition = new THREE.Vector3(); + var quaternion = new THREE.Quaternion(); + var scale = new THREE.Vector3(); + return function () { + var el = this.el; + var object3D = el.object3D; + var camera = el.sceneEl.camera; + var cameraPortalOrientation; + var distance; + var textEl = this.textEl; + if (!this.data.visualAspectEnabled) { + return; + } + + // Update matrices + object3D.updateMatrixWorld(); + camera.parent.updateMatrixWorld(); + camera.updateMatrixWorld(); + object3D.matrix.decompose(elWorldPosition, quaternion, scale); + elWorldPosition.setFromMatrixPosition(object3D.matrixWorld); + cameraWorldPosition.setFromMatrixPosition(camera.matrixWorld); + distance = elWorldPosition.distanceTo(cameraWorldPosition); + if (distance > 20) { + // Store original orientation to be restored when the portal stops facing the camera. + if (!this.previousQuaternion) { + this.quaternionClone.copy(quaternion); + this.previousQuaternion = this.quaternionClone; + } + // If the portal is far away from the user, face portal to camera. + object3D.lookAt(cameraWorldPosition); + } else { + // When portal is close to the user/camera. + cameraPortalOrientation = this.calculateCameraPortalOrientation(); + // If user gets very close to portal, replace with holed sphere they can peek in. + if (distance < 0.5) { + // Configure text size and sphere orientation depending side user approaches portal. + if (this.semiSphereEl.getAttribute('visible') === true) { + return; + } + textEl.setAttribute('text', 'width', 1.5); + if (cameraPortalOrientation <= 0.0) { + textEl.setAttribute('position', '0 0 0.75'); + textEl.setAttribute('rotation', '0 180 0'); + this.semiSphereEl.setAttribute('rotation', '0 0 0'); + } else { + textEl.setAttribute('position', '0 0 -0.75'); + textEl.setAttribute('rotation', '0 0 0'); + this.semiSphereEl.setAttribute('rotation', '0 180 0'); + } + el.getObject3D('mesh').visible = false; + this.semiSphereEl.setAttribute('visible', true); + this.peekCameraPortalOrientation = cameraPortalOrientation; + } else { + // Calculate wich side the camera is approaching the camera (back / front). + // Adjust text orientation based on camera position. + if (cameraPortalOrientation <= 0.0) { + textEl.setAttribute('rotation', '0 180 0'); + } else { + textEl.setAttribute('rotation', '0 0 0'); + } + textEl.setAttribute('text', 'width', 5); + textEl.setAttribute('position', '0 1.5 0'); + el.getObject3D('mesh').visible = true; + this.semiSphereEl.setAttribute('visible', false); + this.peekCameraPortalOrientation = undefined; + } + if (this.previousQuaternion) { + object3D.quaternion.copy(this.previousQuaternion); + this.previousQuaternion = undefined; + } + } + }; + }(), + hideAll: function () { + var el = this.el; + var hiddenEls = this.hiddenEls; + var self = this; + if (hiddenEls.length > 0) { + return; + } + el.sceneEl.object3D.traverse(function (object) { + if (object && object.el && object.el.hasAttribute('link-controls')) { + return; + } + if (!object.el || object === el.sceneEl.object3D || object.el === el || object.el === self.sphereEl || object.el === el.sceneEl.cameraEl || object.el.getAttribute('visible') === false || object.el === self.textEl || object.el === self.semiSphereEl) { + return; + } + object.el.setAttribute('visible', false); + hiddenEls.push(object.el); + }); + }, + showAll: function () { + this.hiddenEls.forEach(function (el) { + el.setAttribute('visible', true); + }); + this.hiddenEls = []; + }, + /** + * Calculate whether the camera faces the front or back face of the portal. + * @returns {number} > 0 if camera faces front of portal, < 0 if it faces back of portal. + */ + calculateCameraPortalOrientation: function () { + var mat4 = new THREE.Matrix4(); + var cameraPosition = new THREE.Vector3(); + var portalNormal = new THREE.Vector3(0, 0, 1); + var portalPosition = new THREE.Vector3(0, 0, 0); + return function () { + var el = this.el; + var camera = el.sceneEl.camera; + + // Reset tmp variables. + cameraPosition.set(0, 0, 0); + portalNormal.set(0, 0, 1); + portalPosition.set(0, 0, 0); + + // Apply portal orientation to the normal. + el.object3D.matrixWorld.extractRotation(mat4); + portalNormal.applyMatrix4(mat4); + + // Calculate portal world position. + el.object3D.updateMatrixWorld(); + el.object3D.localToWorld(portalPosition); + + // Calculate camera world position. + camera.parent.parent.updateMatrixWorld(); + camera.parent.updateMatrixWorld(); + camera.updateMatrixWorld(); + camera.localToWorld(cameraPosition); + + // Calculate vector from portal to camera. + // (portal) -------> (camera) + cameraPosition.sub(portalPosition).normalize(); + portalNormal.normalize(); + + // Side where camera approaches portal is given by sign of dot product of portal normal + // and portal to camera vectors. + return Math.sign(portalNormal.dot(cameraPosition)); + }; + }(), + remove: function () { + this.removeEventListener(); + } +}); + +/* eslint-disable */ +registerShader('portal', { + schema: { + borderEnabled: { + default: 1.0, + type: 'int', + is: 'uniform' + }, + backgroundColor: { + default: 'red', + type: 'color', + is: 'uniform' + }, + pano: { + type: 'map', + is: 'uniform' + }, + strokeColor: { + default: 'white', + type: 'color', + is: 'uniform' + } + }, + vertexShader: ['vec3 portalPosition;', 'varying vec3 vWorldPosition;', 'varying float vDistanceToCenter;', 'varying float vDistance;', 'void main() {', 'vDistanceToCenter = clamp(length(position - vec3(0.0, 0.0, 0.0)), 0.0, 1.0);', 'portalPosition = (modelMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz;', 'vDistance = length(portalPosition - cameraPosition);', 'vWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;', 'gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);', '}'].join('\n'), + fragmentShader: ['#define RECIPROCAL_PI2 0.15915494', 'uniform sampler2D pano;', 'uniform vec3 strokeColor;', 'uniform vec3 backgroundColor;', 'uniform float borderEnabled;', 'varying float vDistanceToCenter;', 'varying float vDistance;', 'varying vec3 vWorldPosition;', 'void main() {', 'vec3 direction = normalize(vWorldPosition - cameraPosition);', 'vec2 sampleUV;', 'float borderThickness = clamp(exp(-vDistance / 50.0), 0.6, 0.95);', 'sampleUV.y = clamp(direction.y * 0.5 + 0.5, 0.0, 1.0);', 'sampleUV.x = atan(direction.z, -direction.x) * -RECIPROCAL_PI2 + 0.5;', 'if (vDistanceToCenter > borderThickness && borderEnabled == 1.0) {', 'gl_FragColor = vec4(strokeColor, 1.0);', '} else {', 'gl_FragColor = mix(texture2D(pano, sampleUV), vec4(backgroundColor, 1.0), clamp(pow((vDistance / 15.0), 2.0), 0.0, 1.0));', '}', '}'].join('\n') +}); +/* eslint-enable */ + +/***/ }), + +/***/ "./src/components/look-controls.js": +/*!*****************************************!*\ + !*** ./src/components/look-controls.js ***! + \*****************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/* global DeviceOrientationEvent */ +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var THREE = __webpack_require__(/*! ../lib/three */ "./src/lib/three.js"); +var utils = __webpack_require__(/*! ../utils/ */ "./src/utils/index.js"); +var bind = utils.bind; + +// To avoid recalculation at every mouse movement tick +var PI_2 = Math.PI / 2; + +/** + * look-controls. Update entity pose, factoring mouse, touch, and WebVR API data. + */ +module.exports.Component = registerComponent('look-controls', { + dependencies: ['position', 'rotation'], + schema: { + enabled: { + default: true + }, + magicWindowTrackingEnabled: { + default: true + }, + pointerLockEnabled: { + default: false + }, + reverseMouseDrag: { + default: false + }, + reverseTouchDrag: { + default: false + }, + touchEnabled: { + default: true + }, + mouseEnabled: { + default: true + } + }, + init: function () { + this.deltaYaw = 0; + this.previousHMDPosition = new THREE.Vector3(); + this.hmdQuaternion = new THREE.Quaternion(); + this.magicWindowAbsoluteEuler = new THREE.Euler(); + this.magicWindowDeltaEuler = new THREE.Euler(); + this.position = new THREE.Vector3(); + this.magicWindowObject = new THREE.Object3D(); + this.rotation = {}; + this.deltaRotation = {}; + this.savedPose = null; + this.pointerLocked = false; + this.setupMouseControls(); + this.bindMethods(); + this.previousMouseEvent = {}; + this.setupMagicWindowControls(); + + // To save / restore camera pose + this.savedPose = { + position: new THREE.Vector3(), + rotation: new THREE.Euler() + }; + + // Call enter VR handler if the scene has entered VR before the event listeners attached. + if (this.el.sceneEl.is('vr-mode') || this.el.sceneEl.is('ar-mode')) { + this.onEnterVR(); + } + }, + setupMagicWindowControls: function () { + var magicWindowControls; + var data = this.data; + + // Only on mobile devices and only enabled if DeviceOrientation permission has been granted. + if (utils.device.isMobile() || utils.device.isMobileDeviceRequestingDesktopSite()) { + magicWindowControls = this.magicWindowControls = new THREE.DeviceOrientationControls(this.magicWindowObject); + if (typeof DeviceOrientationEvent !== 'undefined' && DeviceOrientationEvent.requestPermission) { + magicWindowControls.enabled = false; + // we removed 'device-orientation-permission-ui' as a default enabled component. This is + // a VR specific component. + this.el.sceneEl.addEventListener('deviceorientationpermissiongranted', function () { + magicWindowControls.enabled = data.magicWindowTrackingEnabled; + }); + } + } + }, + update: function (oldData) { + var data = this.data; + + // Disable grab cursor classes if no longer enabled. + if (data.enabled !== oldData.enabled) { + this.updateGrabCursor(data.enabled); + } + + // Reset magic window eulers if tracking is disabled. + if (oldData && !data.magicWindowTrackingEnabled && oldData.magicWindowTrackingEnabled) { + this.magicWindowAbsoluteEuler.set(0, 0, 0); + this.magicWindowDeltaEuler.set(0, 0, 0); + } + + // Pass on magic window tracking setting to magicWindowControls. + if (this.magicWindowControls) { + this.magicWindowControls.enabled = data.magicWindowTrackingEnabled; + } + if (oldData && !data.pointerLockEnabled !== oldData.pointerLockEnabled) { + this.removeEventListeners(); + this.addEventListeners(); + if (this.pointerLocked) { + this.exitPointerLock(); + } + } + }, + tick: function (t) { + var data = this.data; + if (!data.enabled) { + return; + } + this.updateOrientation(); + }, + play: function () { + this.addEventListeners(); + }, + pause: function () { + this.removeEventListeners(); + if (this.pointerLocked) { + this.exitPointerLock(); + } + }, + remove: function () { + this.removeEventListeners(); + if (this.pointerLocked) { + this.exitPointerLock(); + } + }, + bindMethods: function () { + this.onMouseDown = bind(this.onMouseDown, this); + this.onMouseMove = bind(this.onMouseMove, this); + this.onMouseUp = bind(this.onMouseUp, this); + this.onTouchStart = bind(this.onTouchStart, this); + this.onTouchMove = bind(this.onTouchMove, this); + this.onTouchEnd = bind(this.onTouchEnd, this); + this.onEnterVR = bind(this.onEnterVR, this); + this.onExitVR = bind(this.onExitVR, this); + this.onPointerLockChange = bind(this.onPointerLockChange, this); + this.onPointerLockError = bind(this.onPointerLockError, this); + }, + /** + * Set up states and Object3Ds needed to store rotation data. + */ + setupMouseControls: function () { + this.mouseDown = false; + this.pitchObject = new THREE.Object3D(); + this.yawObject = new THREE.Object3D(); + this.yawObject.position.y = 10; + this.yawObject.add(this.pitchObject); + }, + /** + * Add mouse and touch event listeners to canvas. + */ + addEventListeners: function () { + var sceneEl = this.el.sceneEl; + var canvasEl = sceneEl.canvas; + + // Wait for canvas to load. + if (!canvasEl) { + sceneEl.addEventListener('render-target-loaded', bind(this.addEventListeners, this)); + return; + } + + // Mouse events. + canvasEl.addEventListener('mousedown', this.onMouseDown, false); + window.addEventListener('mousemove', this.onMouseMove, false); + window.addEventListener('mouseup', this.onMouseUp, false); + + // Touch events. + canvasEl.addEventListener('touchstart', this.onTouchStart); + window.addEventListener('touchmove', this.onTouchMove); + window.addEventListener('touchend', this.onTouchEnd); + + // sceneEl events. + sceneEl.addEventListener('enter-vr', this.onEnterVR); + sceneEl.addEventListener('exit-vr', this.onExitVR); + + // Pointer Lock events. + if (this.data.pointerLockEnabled) { + document.addEventListener('pointerlockchange', this.onPointerLockChange, false); + document.addEventListener('mozpointerlockchange', this.onPointerLockChange, false); + document.addEventListener('pointerlockerror', this.onPointerLockError, false); + } + }, + /** + * Remove mouse and touch event listeners from canvas. + */ + removeEventListeners: function () { + var sceneEl = this.el.sceneEl; + var canvasEl = sceneEl && sceneEl.canvas; + if (!canvasEl) { + return; + } + + // Mouse events. + canvasEl.removeEventListener('mousedown', this.onMouseDown); + window.removeEventListener('mousemove', this.onMouseMove); + window.removeEventListener('mouseup', this.onMouseUp); + + // Touch events. + canvasEl.removeEventListener('touchstart', this.onTouchStart); + window.removeEventListener('touchmove', this.onTouchMove); + window.removeEventListener('touchend', this.onTouchEnd); + + // sceneEl events. + sceneEl.removeEventListener('enter-vr', this.onEnterVR); + sceneEl.removeEventListener('exit-vr', this.onExitVR); + + // Pointer Lock events. + document.removeEventListener('pointerlockchange', this.onPointerLockChange, false); + document.removeEventListener('mozpointerlockchange', this.onPointerLockChange, false); + document.removeEventListener('pointerlockerror', this.onPointerLockError, false); + }, + /** + * Update orientation for mobile, mouse drag, and headset. + * Mouse-drag only enabled if HMD is not active. + */ + updateOrientation: function () { + var object3D = this.el.object3D; + var pitchObject = this.pitchObject; + var yawObject = this.yawObject; + var sceneEl = this.el.sceneEl; + + // In VR or AR mode, THREE is in charge of updating the camera pose. + if ((sceneEl.is('vr-mode') || sceneEl.is('ar-mode')) && sceneEl.checkHeadsetConnected()) { + // With WebXR THREE applies headset pose to the object3D internally. + return; + } + this.updateMagicWindowOrientation(); + + // On mobile, do camera rotation with touch events and sensors. + object3D.rotation.x = this.magicWindowDeltaEuler.x + pitchObject.rotation.x; + object3D.rotation.y = this.magicWindowDeltaEuler.y + yawObject.rotation.y; + object3D.rotation.z = this.magicWindowDeltaEuler.z; + }, + updateMagicWindowOrientation: function () { + var magicWindowAbsoluteEuler = this.magicWindowAbsoluteEuler; + var magicWindowDeltaEuler = this.magicWindowDeltaEuler; + // Calculate magic window HMD quaternion. + if (this.magicWindowControls && this.magicWindowControls.enabled) { + this.magicWindowControls.update(); + magicWindowAbsoluteEuler.setFromQuaternion(this.magicWindowObject.quaternion, 'YXZ'); + if (!this.previousMagicWindowYaw && magicWindowAbsoluteEuler.y !== 0) { + this.previousMagicWindowYaw = magicWindowAbsoluteEuler.y; + } + if (this.previousMagicWindowYaw) { + magicWindowDeltaEuler.x = magicWindowAbsoluteEuler.x; + magicWindowDeltaEuler.y += magicWindowAbsoluteEuler.y - this.previousMagicWindowYaw; + magicWindowDeltaEuler.z = magicWindowAbsoluteEuler.z; + this.previousMagicWindowYaw = magicWindowAbsoluteEuler.y; + } + } + }, + /** + * Translate mouse drag into rotation. + * + * Dragging up and down rotates the camera around the X-axis (yaw). + * Dragging left and right rotates the camera around the Y-axis (pitch). + */ + onMouseMove: function (evt) { + var direction; + var movementX; + var movementY; + var pitchObject = this.pitchObject; + var previousMouseEvent = this.previousMouseEvent; + var yawObject = this.yawObject; + + // Not dragging or not enabled. + if (!this.data.enabled || !this.mouseDown && !this.pointerLocked) { + return; + } + + // Calculate delta. + if (this.pointerLocked) { + movementX = evt.movementX || evt.mozMovementX || 0; + movementY = evt.movementY || evt.mozMovementY || 0; + } else { + movementX = evt.screenX - previousMouseEvent.screenX; + movementY = evt.screenY - previousMouseEvent.screenY; + } + this.previousMouseEvent.screenX = evt.screenX; + this.previousMouseEvent.screenY = evt.screenY; + + // Calculate rotation. + direction = this.data.reverseMouseDrag ? 1 : -1; + yawObject.rotation.y += movementX * 0.002 * direction; + pitchObject.rotation.x += movementY * 0.002 * direction; + pitchObject.rotation.x = Math.max(-PI_2, Math.min(PI_2, pitchObject.rotation.x)); + }, + /** + * Register mouse down to detect mouse drag. + */ + onMouseDown: function (evt) { + var sceneEl = this.el.sceneEl; + if (!this.data.enabled || !this.data.mouseEnabled || (sceneEl.is('vr-mode') || sceneEl.is('ar-mode')) && sceneEl.checkHeadsetConnected()) { + return; + } + // Handle only primary button. + if (evt.button !== 0) { + return; + } + var canvasEl = sceneEl && sceneEl.canvas; + this.mouseDown = true; + this.previousMouseEvent.screenX = evt.screenX; + this.previousMouseEvent.screenY = evt.screenY; + this.showGrabbingCursor(); + if (this.data.pointerLockEnabled && !this.pointerLocked) { + if (canvasEl.requestPointerLock) { + canvasEl.requestPointerLock(); + } else if (canvasEl.mozRequestPointerLock) { + canvasEl.mozRequestPointerLock(); + } + } + }, + /** + * Shows grabbing cursor on scene + */ + showGrabbingCursor: function () { + this.el.sceneEl.canvas.style.cursor = 'grabbing'; + }, + /** + * Hides grabbing cursor on scene + */ + hideGrabbingCursor: function () { + this.el.sceneEl.canvas.style.cursor = ''; + }, + /** + * Register mouse up to detect release of mouse drag. + */ + onMouseUp: function () { + this.mouseDown = false; + this.hideGrabbingCursor(); + }, + /** + * Register touch down to detect touch drag. + */ + onTouchStart: function (evt) { + if (evt.touches.length !== 1 || !this.data.touchEnabled || this.el.sceneEl.is('vr-mode') || this.el.sceneEl.is('ar-mode')) { + return; + } + this.touchStart = { + x: evt.touches[0].pageX, + y: evt.touches[0].pageY + }; + this.touchStarted = true; + }, + /** + * Translate touch move to Y-axis rotation. + */ + onTouchMove: function (evt) { + var direction; + var canvas = this.el.sceneEl.canvas; + var deltaY; + var yawObject = this.yawObject; + if (!this.touchStarted || !this.data.touchEnabled) { + return; + } + deltaY = 2 * Math.PI * (evt.touches[0].pageX - this.touchStart.x) / canvas.clientWidth; + direction = this.data.reverseTouchDrag ? 1 : -1; + // Limit touch orientaion to to yaw (y axis). + yawObject.rotation.y -= deltaY * 0.5 * direction; + this.touchStart = { + x: evt.touches[0].pageX, + y: evt.touches[0].pageY + }; + }, + /** + * Register touch end to detect release of touch drag. + */ + onTouchEnd: function () { + this.touchStarted = false; + }, + /** + * Save pose. + */ + onEnterVR: function () { + var sceneEl = this.el.sceneEl; + if (!sceneEl.checkHeadsetConnected()) { + return; + } + this.saveCameraPose(); + this.el.object3D.position.set(0, 0, 0); + this.el.object3D.rotation.set(0, 0, 0); + if (sceneEl.hasWebXR) { + this.el.object3D.matrixAutoUpdate = false; + this.el.object3D.updateMatrix(); + } + }, + /** + * Restore the pose. + */ + onExitVR: function () { + if (!this.el.sceneEl.checkHeadsetConnected()) { + return; + } + this.restoreCameraPose(); + this.previousHMDPosition.set(0, 0, 0); + this.el.object3D.matrixAutoUpdate = true; + }, + /** + * Update Pointer Lock state. + */ + onPointerLockChange: function () { + this.pointerLocked = !!(document.pointerLockElement || document.mozPointerLockElement); + }, + /** + * Recover from Pointer Lock error. + */ + onPointerLockError: function () { + this.pointerLocked = false; + }, + // Exits pointer-locked mode. + exitPointerLock: function () { + document.exitPointerLock(); + this.pointerLocked = false; + }, + /** + * Toggle the feature of showing/hiding the grab cursor. + */ + updateGrabCursor: function (enabled) { + var sceneEl = this.el.sceneEl; + function enableGrabCursor() { + sceneEl.canvas.classList.add('a-grab-cursor'); + } + function disableGrabCursor() { + sceneEl.canvas.classList.remove('a-grab-cursor'); + } + if (!sceneEl.canvas) { + if (enabled) { + sceneEl.addEventListener('render-target-loaded', enableGrabCursor); + } else { + sceneEl.addEventListener('render-target-loaded', disableGrabCursor); + } + return; + } + if (enabled) { + enableGrabCursor(); + return; + } + disableGrabCursor(); + }, + /** + * Save camera pose before entering VR to restore later if exiting. + */ + saveCameraPose: function () { + var el = this.el; + this.savedPose.position.copy(el.object3D.position); + this.savedPose.rotation.copy(el.object3D.rotation); + this.hasSavedPose = true; + }, + /** + * Reset camera pose to before entering VR. + */ + restoreCameraPose: function () { + var el = this.el; + var savedPose = this.savedPose; + if (!this.hasSavedPose) { + return; + } + + // Reset camera orientation. + el.object3D.position.copy(savedPose.position); + el.object3D.rotation.copy(savedPose.rotation); + this.hasSavedPose = false; + } +}); + +/***/ }), + +/***/ "./src/components/magicleap-controls.js": +/*!**********************************************!*\ + !*** ./src/components/magicleap-controls.js ***! + \**********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var bind = __webpack_require__(/*! ../utils/bind */ "./src/utils/bind.js"); +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var trackedControlsUtils = __webpack_require__(/*! ../utils/tracked-controls */ "./src/utils/tracked-controls.js"); +var checkControllerPresentAndSetup = trackedControlsUtils.checkControllerPresentAndSetup; +var emitIfAxesChanged = trackedControlsUtils.emitIfAxesChanged; +var onButtonEvent = trackedControlsUtils.onButtonEvent; + +// See Profiles Registry: +// https://github.com/immersive-web/webxr-input-profiles/tree/master/packages/registry +// TODO: Add a more robust system for deriving gamepad name. +var GAMEPAD_ID_PREFIX = 'magicleap'; +var GAMEPAD_ID_SUFFIX = '-one'; +var GAMEPAD_ID_COMPOSITE = GAMEPAD_ID_PREFIX + GAMEPAD_ID_SUFFIX; +var MAGICLEAP_CONTROLLER_MODEL_GLB_URL = 'https://cdn.aframe.io/controllers/magicleap/magicleap-one-controller.glb'; + +/** + * Button IDs: + * 0 - trigger + * 1 - grip + * 2 - touchpad + * 3 - menu (never dispatched on this layer) + * + * Axis: + * 0 - touchpad x axis + * 1 - touchpad y axis + */ +var INPUT_MAPPING_WEBXR = { + axes: { + touchpad: [0, 1] + }, + buttons: ['trigger', 'grip', 'touchpad', 'menu'] +}; + +/** + * Magic Leap Controls + * Interface with Magic Leap control and map Gamepad events to controller + * buttons: trigger, grip, touchpad, and menu. + * Load a controller model. + */ +module.exports.Component = registerComponent('magicleap-controls', { + schema: { + hand: { + default: 'none' + }, + model: { + default: true + }, + orientationOffset: { + type: 'vec3' + } + }, + mapping: INPUT_MAPPING_WEBXR, + init: function () { + var self = this; + this.controllerPresent = false; + this.lastControllerCheck = 0; + this.onButtonChanged = bind(this.onButtonChanged, this); + this.onButtonDown = function (evt) { + onButtonEvent(evt.detail.id, 'down', self); + }; + this.onButtonUp = function (evt) { + onButtonEvent(evt.detail.id, 'up', self); + }; + this.onButtonTouchEnd = function (evt) { + onButtonEvent(evt.detail.id, 'touchend', self); + }; + this.onButtonTouchStart = function (evt) { + onButtonEvent(evt.detail.id, 'touchstart', self); + }; + this.previousButtonValues = {}; + this.rendererSystem = this.el.sceneEl.systems.renderer; + this.bindMethods(); + }, + update: function () { + var data = this.data; + this.controllerIndex = data.hand === 'right' ? 0 : data.hand === 'left' ? 1 : 2; + }, + play: function () { + this.checkIfControllerPresent(); + this.addControllersUpdateListener(); + }, + pause: function () { + this.removeEventListeners(); + this.removeControllersUpdateListener(); + }, + bindMethods: function () { + this.onModelLoaded = bind(this.onModelLoaded, this); + this.onControllersUpdate = bind(this.onControllersUpdate, this); + this.checkIfControllerPresent = bind(this.checkIfControllerPresent, this); + this.removeControllersUpdateListener = bind(this.removeControllersUpdateListener, this); + this.onAxisMoved = bind(this.onAxisMoved, this); + }, + addEventListeners: function () { + var el = this.el; + el.addEventListener('buttonchanged', this.onButtonChanged); + el.addEventListener('buttondown', this.onButtonDown); + el.addEventListener('buttonup', this.onButtonUp); + el.addEventListener('touchstart', this.onButtonTouchStart); + el.addEventListener('touchend', this.onButtonTouchEnd); + el.addEventListener('axismove', this.onAxisMoved); + el.addEventListener('model-loaded', this.onModelLoaded); + this.controllerEventsActive = true; + }, + removeEventListeners: function () { + var el = this.el; + el.removeEventListener('buttonchanged', this.onButtonChanged); + el.removeEventListener('buttondown', this.onButtonDown); + el.removeEventListener('buttonup', this.onButtonUp); + el.removeEventListener('touchstart', this.onButtonTouchStart); + el.removeEventListener('touchend', this.onButtonTouchEnd); + el.removeEventListener('axismove', this.onAxisMoved); + el.removeEventListener('model-loaded', this.onModelLoaded); + this.controllerEventsActive = false; + }, + checkIfControllerPresent: function () { + var data = this.data; + checkControllerPresentAndSetup(this, GAMEPAD_ID_COMPOSITE, { + index: this.controllerIndex, + hand: data.hand + }); + }, + injectTrackedControls: function () { + var el = this.el; + var data = this.data; + el.setAttribute('tracked-controls', { + // TODO: verify expected behavior between reserved prefixes. + idPrefix: GAMEPAD_ID_COMPOSITE, + hand: data.hand, + controller: this.controllerIndex, + orientationOffset: data.orientationOffset + }); + + // Load model. + if (!this.data.model) { + return; + } + this.el.setAttribute('gltf-model', MAGICLEAP_CONTROLLER_MODEL_GLB_URL); + }, + addControllersUpdateListener: function () { + this.el.sceneEl.addEventListener('controllersupdated', this.onControllersUpdate, false); + }, + removeControllersUpdateListener: function () { + this.el.sceneEl.removeEventListener('controllersupdated', this.onControllersUpdate, false); + }, + onControllersUpdate: function () { + // Note that due to gamepadconnected event propagation issues, we don't rely on events. + this.checkIfControllerPresent(); + }, + /** + * Rotate the trigger button based on how hard the trigger is pressed. + */ + onButtonChanged: function (evt) { + var button = this.mapping.buttons[evt.detail.id]; + var analogValue; + if (!button) { + return; + } + if (button === 'trigger') { + analogValue = evt.detail.state.value; + console.log('analog value of trigger press: ' + analogValue); + } + + // Pass along changed event with button state, using button mapping for convenience. + this.el.emit(button + 'changed', evt.detail.state); + }, + onModelLoaded: function (evt) { + var controllerObject3D = evt.detail.model; + // our glb scale is too large. + controllerObject3D.scale.set(0.01, 0.01, 0.01); + }, + onAxisMoved: function (evt) { + emitIfAxesChanged(this, this.mapping.axes, evt); + }, + updateModel: function (buttonName, evtName) {}, + setButtonColor: function (buttonName, color) {} +}); + +/***/ }), + +/***/ "./src/components/material.js": +/*!************************************!*\ + !*** ./src/components/material.js ***! + \************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/* global Promise */ +var utils = __webpack_require__(/*! ../utils/ */ "./src/utils/index.js"); +var component = __webpack_require__(/*! ../core/component */ "./src/core/component.js"); +var THREE = __webpack_require__(/*! ../lib/three */ "./src/lib/three.js"); +var shader = __webpack_require__(/*! ../core/shader */ "./src/core/shader.js"); +var error = utils.debug('components:material:error'); +var registerComponent = component.registerComponent; +var shaders = shader.shaders; +var shaderNames = shader.shaderNames; + +/** + * Material component. + * + * @member {object} shader - Determines how material is shaded. Defaults to `standard`, + * three.js's implementation of PBR. Another standard shading model is `flat` which + * uses MeshBasicMaterial. + */ +module.exports.Component = registerComponent('material', { + schema: { + alphaTest: { + default: 0.0, + min: 0.0, + max: 1.0 + }, + depthTest: { + default: true + }, + depthWrite: { + default: true + }, + flatShading: { + default: false + }, + npot: { + default: false + }, + offset: { + type: 'vec2', + default: { + x: 0, + y: 0 + } + }, + opacity: { + default: 1.0, + min: 0.0, + max: 1.0 + }, + repeat: { + type: 'vec2', + default: { + x: 1, + y: 1 + } + }, + shader: { + default: 'standard', + oneOf: shaderNames, + schemaChange: true + }, + side: { + default: 'front', + oneOf: ['front', 'back', 'double'] + }, + transparent: { + default: false + }, + vertexColors: { + type: 'string', + default: 'none', + oneOf: ['face', 'vertex'] + }, + visible: { + default: true + }, + blending: { + default: 'normal', + oneOf: ['none', 'normal', 'additive', 'subtractive', 'multiply'] + }, + dithering: { + default: true + } + }, + init: function () { + this.material = null; + }, + /** + * Update or create material. + * + * @param {object|null} oldData + */ + update: function (oldData) { + var data = this.data; + if (!this.shader || data.shader !== oldData.shader) { + this.updateShader(data.shader); + } + this.shader.update(this.data); + this.updateMaterial(oldData); + }, + updateSchema: function (data) { + var currentShader; + var newShader; + var schema; + var shader; + newShader = data && data.shader; + currentShader = this.oldData && this.oldData.shader; + shader = newShader || currentShader; + schema = shaders[shader] && shaders[shader].schema; + if (!schema) { + error('Unknown shader schema ' + shader); + } + if (currentShader && newShader === currentShader) { + return; + } + this.extendSchema(schema); + this.updateBehavior(); + }, + updateBehavior: function () { + var key; + var sceneEl = this.el.sceneEl; + var schema = this.schema; + var self = this; + var tickProperties; + function tickTime(time, delta) { + var key; + for (key in tickProperties) { + tickProperties[key] = time; + } + self.shader.update(tickProperties); + } + this.tick = undefined; + tickProperties = {}; + for (key in schema) { + if (schema[key].type === 'time') { + this.tick = tickTime; + tickProperties[key] = true; + } + } + if (!sceneEl) { + return; + } + if (this.tick) { + sceneEl.addBehavior(this); + } else { + sceneEl.removeBehavior(this); + } + }, + updateShader: function (shaderName) { + var data = this.data; + var Shader = shaders[shaderName] && shaders[shaderName].Shader; + var shaderInstance; + if (!Shader) { + throw new Error('Unknown shader ' + shaderName); + } + + // Get material from A-Frame shader. + shaderInstance = this.shader = new Shader(); + shaderInstance.el = this.el; + shaderInstance.init(data); + this.setMaterial(shaderInstance.material); + this.updateSchema(data); + }, + /** + * Set and update base material properties. + * Set `needsUpdate` when needed. + */ + updateMaterial: function (oldData) { + var data = this.data; + var material = this.material; + var oldDataHasKeys; + + // Base material properties. + material.alphaTest = data.alphaTest; + material.depthTest = data.depthTest !== false; + material.depthWrite = data.depthWrite !== false; + material.opacity = data.opacity; + material.flatShading = data.flatShading; + material.side = parseSide(data.side); + material.transparent = data.transparent !== false || data.opacity < 1.0 || data.shader === 'shadow'; + material.vertexColors = parseVertexColors(data.vertexColors); + material.visible = data.visible; + material.blending = parseBlending(data.blending); + material.dithering = data.dithering; + + // Check if material needs update. + for (oldDataHasKeys in oldData) { + break; + } + if (oldDataHasKeys && (oldData.alphaTest !== data.alphaTest || oldData.side !== data.side || oldData.vertexColors !== data.vertexColors)) { + material.needsUpdate = true; + } + }, + /** + * Remove material on remove (callback). + * Dispose of it from memory and unsubscribe from scene updates. + */ + remove: function () { + var defaultMaterial = new THREE.MeshBasicMaterial(); + var material = this.material; + var object3D = this.el.getObject3D('mesh'); + if (object3D) { + object3D.material = defaultMaterial; + } + disposeMaterial(material, this.system); + }, + /** + * (Re)create new material. Has side-effects of setting `this.material` and updating + * material registration in scene. + * + * @param {object} data - Material component data. + * @param {object} type - Material type to create. + * @returns {object} Material. + */ + setMaterial: function (material) { + var el = this.el; + var mesh; + var system = this.system; + if (this.material) { + disposeMaterial(this.material, system); + } + this.material = material; + system.registerMaterial(material); + + // Set on mesh. If mesh does not exist, wait for it. + mesh = el.getObject3D('mesh'); + if (mesh) { + mesh.material = material; + } else { + el.addEventListener('object3dset', function waitForMesh(evt) { + if (evt.detail.type !== 'mesh' || evt.target !== el) { + return; + } + el.getObject3D('mesh').material = material; + el.removeEventListener('object3dset', waitForMesh); + }); + } + } +}); + +/** + * Return a three.js constant determining which material face sides to render + * based on the side parameter (passed as a component property). + * + * @param {string} [side=front] - `front`, `back`, or `double`. + * @returns {number} THREE.FrontSide, THREE.BackSide, or THREE.DoubleSide. + */ +function parseSide(side) { + switch (side) { + case 'back': + { + return THREE.BackSide; + } + case 'double': + { + return THREE.DoubleSide; + } + default: + { + // Including case `front`. + return THREE.FrontSide; + } + } +} + +/** + * Return a three.js constant determining vertex coloring. + */ +function parseVertexColors(coloring) { + switch (coloring) { + case 'face': + { + return THREE.FaceColors; + } + case 'vertex': + { + return THREE.VertexColors; + } + default: + { + return THREE.NoColors; + } + } +} + +/** + * Return a three.js constant determining blending + * + * @param {string} [blending=normal] + * - `none`, additive`, `subtractive`,`multiply` or `normal`. + * @returns {number} + */ +function parseBlending(blending) { + switch (blending) { + case 'none': + { + return THREE.NoBlending; + } + case 'additive': + { + return THREE.AdditiveBlending; + } + case 'subtractive': + { + return THREE.SubtractiveBlending; + } + case 'multiply': + { + return THREE.MultiplyBlending; + } + default: + { + return THREE.NormalBlending; + } + } +} + +/** + * Dispose of material from memory and unsubscribe material from scene updates like fog. + */ +function disposeMaterial(material, system) { + material.dispose(); + system.unregisterMaterial(material); +} + +/***/ }), + +/***/ "./src/components/obj-model.js": +/*!*************************************!*\ + !*** ./src/components/obj-model.js ***! + \*************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var debug = __webpack_require__(/*! ../utils/debug */ "./src/utils/debug.js"); +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var THREE = __webpack_require__(/*! ../lib/three */ "./src/lib/three.js"); +var warn = debug('components:obj-model:warn'); +module.exports.Component = registerComponent('obj-model', { + schema: { + mtl: { + type: 'model' + }, + obj: { + type: 'model' + } + }, + init: function () { + var self = this; + this.model = null; + this.objLoader = new THREE.OBJLoader(); + this.mtlLoader = new THREE.MTLLoader(this.objLoader.manager); + // Allow cross-origin images to be loaded. + this.mtlLoader.crossOrigin = ''; + this.el.addEventListener('componentinitialized', function (evt) { + if (!self.model) { + return; + } + if (evt.detail.name !== 'material') { + return; + } + self.applyMaterial(); + }); + }, + update: function () { + var data = this.data; + if (!data.obj) { + return; + } + this.resetMesh(); + this.loadObj(data.obj, data.mtl); + }, + remove: function () { + if (!this.model) { + return; + } + this.resetMesh(); + }, + resetMesh: function () { + this.el.removeObject3D('mesh'); + }, + loadObj: function (objUrl, mtlUrl) { + var self = this; + var el = this.el; + var mtlLoader = this.mtlLoader; + var objLoader = this.objLoader; + var rendererSystem = this.el.sceneEl.systems.renderer; + var BASE_PATH = mtlUrl.substr(0, mtlUrl.lastIndexOf('/') + 1); + if (mtlUrl) { + // .OBJ with an .MTL. + if (el.hasAttribute('material')) { + warn('Material component properties are ignored when a .MTL is provided'); + } + mtlLoader.setResourcePath(BASE_PATH); + mtlLoader.load(mtlUrl, function (materials) { + materials.preload(); + objLoader.setMaterials(materials); + objLoader.load(objUrl, function (objModel) { + self.model = objModel; + self.model.traverse(function (object) { + if (object.isMesh) { + var material = object.material; + if (material.color) rendererSystem.applyColorCorrection(material.color); + if (material.map) rendererSystem.applyColorCorrection(material.map); + if (material.emissive) rendererSystem.applyColorCorrection(material.emissive); + if (material.emissiveMap) rendererSystem.applyColorCorrection(material.emissiveMap); + } + }); + el.setObject3D('mesh', objModel); + el.emit('model-loaded', { + format: 'obj', + model: objModel + }); + }); + }); + return; + } + + // .OBJ only. + objLoader.load(objUrl, function loadObjOnly(objModel) { + self.model = objModel; + self.applyMaterial(); + el.setObject3D('mesh', objModel); + el.emit('model-loaded', { + format: 'obj', + model: objModel + }); + }); + }, + /** + * Apply material from material component recursively. + */ + applyMaterial: function () { + var material = this.el.components.material; + if (!material) { + return; + } + this.model.traverse(function (child) { + if (child instanceof THREE.Mesh) { + child.material = material.material; + } + }); + } +}); + +/***/ }), + +/***/ "./src/components/oculus-go-controls.js": +/*!**********************************************!*\ + !*** ./src/components/oculus-go-controls.js ***! + \**********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var bind = __webpack_require__(/*! ../utils/bind */ "./src/utils/bind.js"); +var trackedControlsUtils = __webpack_require__(/*! ../utils/tracked-controls */ "./src/utils/tracked-controls.js"); +var checkControllerPresentAndSetup = trackedControlsUtils.checkControllerPresentAndSetup; +var emitIfAxesChanged = trackedControlsUtils.emitIfAxesChanged; +var onButtonEvent = trackedControlsUtils.onButtonEvent; +var isWebXRAvailable = (__webpack_require__(/*! ../utils/ */ "./src/utils/index.js").device.isWebXRAvailable); +var GAMEPAD_ID_WEBXR = 'oculus-go'; +var GAMEPAD_ID_WEBVR = 'Oculus Go'; +var OCULUS_GO_CONTROLLER_MODEL_URL = 'https://cdn.aframe.io/controllers/oculus/go/oculus-go-controller.gltf'; + +// Prefix for Gen1 and Gen2 Oculus Touch Controllers. +var GAMEPAD_ID_PREFIX = isWebXRAvailable ? GAMEPAD_ID_WEBXR : GAMEPAD_ID_WEBVR; + +/** + * Button indices: + * 0 - trackpad + * 1 - trigger + * + * Axis: + * 0 - trackpad x + * 1 - trackpad y + */ +var INPUT_MAPPING_WEBVR = { + axes: { + trackpad: [0, 1] + }, + buttons: ['trackpad', 'trigger'] +}; + +/** + * Button indices: + * 0 - trigger + * 1 - none + * 2 - touchpad + * + * Axis: + * 0 - touchpad x + * 1 - touchpad y + * Reference: https://github.com/immersive-web/webxr-input-profiles/blob/master/packages/registry/profiles/oculus/oculus-go.json + */ +var INPUT_MAPPING_WEBXR = { + axes: { + touchpad: [0, 1] + }, + buttons: ['trigger', 'none', 'touchpad'] +}; +var INPUT_MAPPING = isWebXRAvailable ? INPUT_MAPPING_WEBXR : INPUT_MAPPING_WEBVR; + +/** + * Oculus Go controls. + * Interface with Oculus Go controller and map Gamepad events to + * controller buttons: trackpad, trigger + * Load a controller model and highlight the pressed buttons. + */ +module.exports.Component = registerComponent('oculus-go-controls', { + schema: { + hand: { + default: '' + }, + // This informs the degenerate arm model. + buttonColor: { + type: 'color', + default: '#FFFFFF' + }, + buttonTouchedColor: { + type: 'color', + default: '#BBBBBB' + }, + buttonHighlightColor: { + type: 'color', + default: '#7A7A7A' + }, + model: { + default: true + }, + orientationOffset: { + type: 'vec3' + }, + armModel: { + default: true + } + }, + mapping: INPUT_MAPPING, + bindMethods: function () { + this.onModelLoaded = bind(this.onModelLoaded, this); + this.onControllersUpdate = bind(this.onControllersUpdate, this); + this.checkIfControllerPresent = bind(this.checkIfControllerPresent, this); + this.removeControllersUpdateListener = bind(this.removeControllersUpdateListener, this); + this.onAxisMoved = bind(this.onAxisMoved, this); + }, + init: function () { + var self = this; + this.onButtonChanged = bind(this.onButtonChanged, this); + this.onButtonDown = function (evt) { + onButtonEvent(evt.detail.id, 'down', self); + }; + this.onButtonUp = function (evt) { + onButtonEvent(evt.detail.id, 'up', self); + }; + this.onButtonTouchStart = function (evt) { + onButtonEvent(evt.detail.id, 'touchstart', self); + }; + this.onButtonTouchEnd = function (evt) { + onButtonEvent(evt.detail.id, 'touchend', self); + }; + this.controllerPresent = false; + this.lastControllerCheck = 0; + this.rendererSystem = this.el.sceneEl.systems.renderer; + this.bindMethods(); + }, + addEventListeners: function () { + var el = this.el; + el.addEventListener('buttonchanged', this.onButtonChanged); + el.addEventListener('buttondown', this.onButtonDown); + el.addEventListener('buttonup', this.onButtonUp); + el.addEventListener('touchstart', this.onButtonTouchStart); + el.addEventListener('touchend', this.onButtonTouchEnd); + el.addEventListener('model-loaded', this.onModelLoaded); + el.addEventListener('axismove', this.onAxisMoved); + this.controllerEventsActive = true; + }, + removeEventListeners: function () { + var el = this.el; + el.removeEventListener('buttonchanged', this.onButtonChanged); + el.removeEventListener('buttondown', this.onButtonDown); + el.removeEventListener('buttonup', this.onButtonUp); + el.removeEventListener('touchstart', this.onButtonTouchStart); + el.removeEventListener('touchend', this.onButtonTouchEnd); + el.removeEventListener('model-loaded', this.onModelLoaded); + el.removeEventListener('axismove', this.onAxisMoved); + this.controllerEventsActive = false; + }, + checkIfControllerPresent: function () { + checkControllerPresentAndSetup(this, GAMEPAD_ID_PREFIX, this.data.hand ? { + hand: this.data.hand + } : {}); + }, + play: function () { + this.checkIfControllerPresent(); + this.addControllersUpdateListener(); + }, + pause: function () { + this.removeEventListeners(); + this.removeControllersUpdateListener(); + }, + injectTrackedControls: function () { + var el = this.el; + var data = this.data; + el.setAttribute('tracked-controls', { + armModel: data.armModel, + hand: data.hand, + idPrefix: GAMEPAD_ID_PREFIX, + orientationOffset: data.orientationOffset + }); + if (!this.data.model) { + return; + } + this.el.setAttribute('gltf-model', OCULUS_GO_CONTROLLER_MODEL_URL); + }, + addControllersUpdateListener: function () { + this.el.sceneEl.addEventListener('controllersupdated', this.onControllersUpdate, false); + }, + removeControllersUpdateListener: function () { + this.el.sceneEl.removeEventListener('controllersupdated', this.onControllersUpdate, false); + }, + onControllersUpdate: function () { + this.checkIfControllerPresent(); + }, + // No need for onButtonChanged, since Oculus Go controller has no analog buttons. + + onModelLoaded: function (evt) { + var controllerObject3D = evt.detail.model; + var buttonMeshes; + if (!this.data.model) { + return; + } + buttonMeshes = this.buttonMeshes = {}; + buttonMeshes.trigger = controllerObject3D.getObjectByName('oculus_go_button_trigger'); + buttonMeshes.trackpad = controllerObject3D.getObjectByName('oculus_go_touchpad'); + buttonMeshes.touchpad = controllerObject3D.getObjectByName('oculus_go_touchpad'); + }, + onButtonChanged: function (evt) { + var button = this.mapping.buttons[evt.detail.id]; + if (!button) return; + // Pass along changed event with button state, using button mapping for convenience. + this.el.emit(button + 'changed', evt.detail.state); + }, + onAxisMoved: function (evt) { + emitIfAxesChanged(this, this.mapping.axes, evt); + }, + updateModel: function (buttonName, evtName) { + if (!this.data.model) { + return; + } + this.updateButtonModel(buttonName, evtName); + }, + updateButtonModel: function (buttonName, state) { + var buttonMeshes = this.buttonMeshes; + if (!buttonMeshes || !buttonMeshes[buttonName]) { + return; + } + var color; + var button; + switch (state) { + case 'down': + color = this.data.buttonHighlightColor; + break; + case 'touchstart': + color = this.data.buttonTouchedColor; + break; + default: + color = this.data.buttonColor; + } + button = buttonMeshes[buttonName]; + button.material.color.set(color); + this.rendererSystem.applyColorCorrection(button.material.color); + } +}); + +/***/ }), + +/***/ "./src/components/oculus-touch-controls.js": +/*!*************************************************!*\ + !*** ./src/components/oculus-touch-controls.js ***! + \*************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var bind = __webpack_require__(/*! ../utils/bind */ "./src/utils/bind.js"); +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var THREE = __webpack_require__(/*! ../lib/three */ "./src/lib/three.js"); +var trackedControlsUtils = __webpack_require__(/*! ../utils/tracked-controls */ "./src/utils/tracked-controls.js"); +var checkControllerPresentAndSetup = trackedControlsUtils.checkControllerPresentAndSetup; +var emitIfAxesChanged = trackedControlsUtils.emitIfAxesChanged; +var onButtonEvent = trackedControlsUtils.onButtonEvent; +var isWebXRAvailable = (__webpack_require__(/*! ../utils/ */ "./src/utils/index.js").device.isWebXRAvailable); +var GAMEPAD_ID_WEBXR = 'oculus-touch'; +var GAMEPAD_ID_WEBVR = 'Oculus Touch'; + +// Prefix for Gen1 and Gen2 Oculus Touch Controllers. +var GAMEPAD_ID_PREFIX = isWebXRAvailable ? GAMEPAD_ID_WEBXR : GAMEPAD_ID_WEBVR; + +// First generation model URL. +var TOUCH_CONTROLLER_MODEL_BASE_URL = 'https://cdn.aframe.io/controllers/oculus/oculus-touch-controller-'; +var META_CONTROLLER_MODEL_BASE_URL = 'https://cdn.aframe.io/controllers/meta/'; +var OCULUS_TOUCH_WEBVR = { + left: { + modelUrl: TOUCH_CONTROLLER_MODEL_BASE_URL + 'left.gltf', + rayOrigin: { + origin: { + x: 0.008, + y: -0.01, + z: 0 + }, + direction: { + x: 0, + y: -0.8, + z: -1 + } + }, + modelPivotOffset: new THREE.Vector3(-0.005, 0.003, -0.055), + modelPivotRotation: new THREE.Euler(0, 0, 0) + }, + right: { + modelUrl: TOUCH_CONTROLLER_MODEL_BASE_URL + 'right.gltf', + rayOrigin: { + origin: { + x: -0.008, + y: -0.01, + z: 0 + }, + direction: { + x: 0, + y: -0.8, + z: -1 + } + }, + modelPivotOffset: new THREE.Vector3(0.005, 0.003, -0.055), + modelPivotRotation: new THREE.Euler(0, 0, 0) + } +}; +var OCULUS_TOUCH_WEBXR = { + left: { + modelUrl: TOUCH_CONTROLLER_MODEL_BASE_URL + 'left.gltf', + rayOrigin: { + origin: { + x: 0.002, + y: -0.005, + z: -0.03 + }, + direction: { + x: 0, + y: -0.8, + z: -1 + } + }, + modelPivotOffset: new THREE.Vector3(-0.005, 0.036, -0.037), + modelPivotRotation: new THREE.Euler(Math.PI / 4.5, 0, 0) + }, + right: { + modelUrl: TOUCH_CONTROLLER_MODEL_BASE_URL + 'right.gltf', + rayOrigin: { + origin: { + x: -0.002, + y: -0.005, + z: -0.03 + }, + direction: { + x: 0, + y: -0.8, + z: -1 + } + }, + modelPivotOffset: new THREE.Vector3(0.005, 0.036, -0.037), + modelPivotRotation: new THREE.Euler(Math.PI / 4.5, 0, 0) + } +}; +var OCULUS_TOUCH_CONFIG = isWebXRAvailable ? OCULUS_TOUCH_WEBXR : OCULUS_TOUCH_WEBVR; +var CONTROLLER_DEFAULT = 'oculus-touch'; +var CONTROLLER_PROPERTIES = { + 'oculus-touch': OCULUS_TOUCH_CONFIG, + 'oculus-touch-v2': { + left: { + modelUrl: TOUCH_CONTROLLER_MODEL_BASE_URL + 'gen2-left.gltf', + rayOrigin: { + origin: { + x: -0.006, + y: -0.03, + z: -0.04 + }, + direction: { + x: 0, + y: -0.9, + z: -1 + } + }, + modelPivotOffset: new THREE.Vector3(0, -0.007, -0.021), + modelPivotRotation: new THREE.Euler(-Math.PI / 4, 0, 0) + }, + right: { + modelUrl: TOUCH_CONTROLLER_MODEL_BASE_URL + 'gen2-right.gltf', + rayOrigin: { + origin: { + x: 0.006, + y: -0.03, + z: -0.04 + }, + direction: { + x: 0, + y: -0.9, + z: -1 + } + }, + modelPivotOffset: new THREE.Vector3(0, -0.007, -0.021), + modelPivotRotation: new THREE.Euler(-Math.PI / 4, 0, 0) + } + }, + 'oculus-touch-v3': { + left: { + modelUrl: TOUCH_CONTROLLER_MODEL_BASE_URL + 'v3-left.glb', + rayOrigin: { + origin: { + x: 0.0065, + y: -0.0186, + z: -0.05 + }, + direction: { + x: 0.12394785839500175, + y: -0.5944043672340157, + z: -0.7945567170519814 + } + }, + modelPivotOffset: new THREE.Vector3(0, 0, 0), + modelPivotRotation: new THREE.Euler(0, 0, 0) + }, + right: { + modelUrl: TOUCH_CONTROLLER_MODEL_BASE_URL + 'v3-right.glb', + rayOrigin: { + origin: { + x: -0.0065, + y: -0.0186, + z: -0.05 + }, + direction: { + x: -0.12394785839500175, + y: -0.5944043672340157, + z: -0.7945567170519814 + } + }, + modelPivotOffset: new THREE.Vector3(0, 0, 0), + modelPivotRotation: new THREE.Euler(0, 0, 0) + } + }, + 'meta-quest-touch-pro': { + left: { + modelUrl: META_CONTROLLER_MODEL_BASE_URL + 'quest-touch-pro-left.glb', + rayOrigin: { + origin: { + x: 0.0065, + y: -0.0186, + z: -0.05 + }, + direction: { + x: 0.12394785839500175, + y: -0.5944043672340157, + z: -0.7945567170519814 + } + }, + modelPivotOffset: new THREE.Vector3(0, 0, 0), + modelPivotRotation: new THREE.Euler(0, 0, 0) + }, + right: { + modelUrl: META_CONTROLLER_MODEL_BASE_URL + 'quest-touch-pro-right.glb', + rayOrigin: { + origin: { + x: -0.0065, + y: -0.0186, + z: -0.05 + }, + direction: { + x: -0.12394785839500175, + y: -0.5944043672340157, + z: -0.7945567170519814 + } + }, + modelPivotOffset: new THREE.Vector3(0, 0, 0), + modelPivotRotation: new THREE.Euler(0, 0, 0) + } + } +}; + +/** + * Button indices: + * 0 - thumbstick (which has separate axismove / thumbstickmoved events) + * 1 - trigger (with analog value, which goes up to 1) + * 2 - grip (with analog value, which goes up to 1) + * 3 - X (left) or A (right) + * 4 - Y (left) or B (right) + * 5 - surface (touch only) + */ +var INPUT_MAPPING_WEBVR = { + left: { + axes: { + thumbstick: [0, 1] + }, + buttons: ['thumbstick', 'trigger', 'grip', 'xbutton', 'ybutton', 'surface'] + }, + right: { + axes: { + thumbstick: [0, 1] + }, + buttons: ['thumbstick', 'trigger', 'grip', 'abutton', 'bbutton', 'surface'] + } +}; + +/** + * Button indices: + * 0 - trigger + * 1 - grip + * 2 - none + * 3 - thumbstick + * 4 - X or A button + * 5 - Y or B button + * 6 - surface + * + * Axis: + * 0 - none + * 1 - none + * 2 - thumbstick + * 3 - thumbstick + * Reference: https://github.com/immersive-web/webxr-input-profiles/blob/master/packages/registry/profiles/oculus/oculus-touch.json + */ +var INPUT_MAPPING_WEBXR = { + left: { + axes: { + thumbstick: [2, 3] + }, + buttons: ['trigger', 'grip', 'none', 'thumbstick', 'xbutton', 'ybutton', 'surface'] + }, + right: { + axes: { + thumbstick: [2, 3] + }, + buttons: ['trigger', 'grip', 'none', 'thumbstick', 'abutton', 'bbutton', 'surface'] + } +}; +var INPUT_MAPPING = isWebXRAvailable ? INPUT_MAPPING_WEBXR : INPUT_MAPPING_WEBVR; + +/** + * Oculus Touch controls. + * Interface with Oculus Touch controllers and map Gamepad events to + * controller buttons: thumbstick, trigger, grip, xbutton, ybutton, surface + * Load a controller model and highlight the pressed buttons. + */ +module.exports.Component = registerComponent('oculus-touch-controls', { + schema: { + hand: { + default: 'left' + }, + buttonColor: { + type: 'color', + default: '#999' + }, + // Off-white. + buttonTouchColor: { + type: 'color', + default: '#8AB' + }, + buttonHighlightColor: { + type: 'color', + default: '#2DF' + }, + // Light blue. + model: { + default: true + }, + controllerType: { + default: 'auto', + oneOf: ['auto', 'oculus-touch', 'oculus-touch-v2', 'oculus-touch-v3'] + }, + orientationOffset: { + type: 'vec3', + default: { + x: 43, + y: 0, + z: 0 + } + } + }, + mapping: INPUT_MAPPING, + bindMethods: function () { + this.onButtonChanged = bind(this.onButtonChanged, this); + this.onThumbstickMoved = bind(this.onThumbstickMoved, this); + this.onModelLoaded = bind(this.onModelLoaded, this); + this.onControllersUpdate = bind(this.onControllersUpdate, this); + this.checkIfControllerPresent = bind(this.checkIfControllerPresent, this); + this.onAxisMoved = bind(this.onAxisMoved, this); + }, + init: function () { + var self = this; + this.onButtonDown = function (evt) { + onButtonEvent(evt.detail.id, 'down', self, self.data.hand); + }; + this.onButtonUp = function (evt) { + onButtonEvent(evt.detail.id, 'up', self, self.data.hand); + }; + this.onButtonTouchStart = function (evt) { + onButtonEvent(evt.detail.id, 'touchstart', self, self.data.hand); + }; + this.onButtonTouchEnd = function (evt) { + onButtonEvent(evt.detail.id, 'touchend', self, self.data.hand); + }; + this.controllerPresent = false; + this.lastControllerCheck = 0; + this.previousButtonValues = {}; + this.rendererSystem = this.el.sceneEl.systems.renderer; + this.bindMethods(); + this.triggerEuler = new THREE.Euler(); + }, + addEventListeners: function () { + var el = this.el; + el.addEventListener('buttonchanged', this.onButtonChanged); + el.addEventListener('buttondown', this.onButtonDown); + el.addEventListener('buttonup', this.onButtonUp); + el.addEventListener('touchstart', this.onButtonTouchStart); + el.addEventListener('touchend', this.onButtonTouchEnd); + el.addEventListener('axismove', this.onAxisMoved); + el.addEventListener('model-loaded', this.onModelLoaded); + el.addEventListener('thumbstickmoved', this.onThumbstickMoved); + this.controllerEventsActive = true; + }, + removeEventListeners: function () { + var el = this.el; + el.removeEventListener('buttonchanged', this.onButtonChanged); + el.removeEventListener('buttondown', this.onButtonDown); + el.removeEventListener('buttonup', this.onButtonUp); + el.removeEventListener('touchstart', this.onButtonTouchStart); + el.removeEventListener('touchend', this.onButtonTouchEnd); + el.removeEventListener('axismove', this.onAxisMoved); + el.removeEventListener('model-loaded', this.onModelLoaded); + el.removeEventListener('thumbstickmoved', this.onThumbstickMoved); + this.controllerEventsActive = false; + }, + checkIfControllerPresent: function () { + checkControllerPresentAndSetup(this, GAMEPAD_ID_PREFIX, { + hand: this.data.hand, + iterateControllerProfiles: true + }); + }, + play: function () { + this.checkIfControllerPresent(); + this.addControllersUpdateListener(); + }, + pause: function () { + this.removeEventListeners(); + this.removeControllersUpdateListener(); + }, + loadModel: function (controller) { + var data = this.data; + var controllerId; + if (!data.model) { + return; + } + // Set the controller display model based on the data passed in. + this.displayModel = CONTROLLER_PROPERTIES[data.controllerType] || CONTROLLER_PROPERTIES[CONTROLLER_DEFAULT]; + // If the developer is asking for auto-detection, use the retrieved displayName to identify the specific unit. + // This only works for WebVR currently. + if (data.controllerType === 'auto') { + var trackedControlsSystem = this.el.sceneEl.systems['tracked-controls-webvr']; + // WebVR + if (trackedControlsSystem && trackedControlsSystem.vrDisplay) { + var displayName = trackedControlsSystem.vrDisplay.displayName; + if (/^Oculus Quest$/.test(displayName)) { + this.displayModel = CONTROLLER_PROPERTIES['oculus-touch-v2']; + } + } else { + // WebXR + controllerId = CONTROLLER_DEFAULT; + var controllersPropertiesIds = Object.keys(CONTROLLER_PROPERTIES); + for (var i = 0; i < controller.profiles.length; i++) { + if (controllersPropertiesIds.indexOf(controller.profiles[i]) !== -1) { + controllerId = controller.profiles[i]; + break; + } + } + this.displayModel = CONTROLLER_PROPERTIES[controllerId]; + } + } + var modelUrl = this.displayModel[data.hand].modelUrl; + this.isOculusTouchV3 = this.displayModel === CONTROLLER_PROPERTIES['oculus-touch-v3']; + this.el.setAttribute('gltf-model', modelUrl); + }, + injectTrackedControls: function (controller) { + var data = this.data; + var webXRId = GAMEPAD_ID_WEBXR; + var webVRId = data.hand === 'right' ? 'Oculus Touch (Right)' : 'Oculus Touch (Left)'; + var id = isWebXRAvailable ? webXRId : webVRId; + this.el.setAttribute('tracked-controls', { + id: id, + hand: data.hand, + orientationOffset: data.orientationOffset, + handTrackingEnabled: false, + iterateControllerProfiles: true, + space: 'gripSpace' + }); + this.loadModel(controller); + }, + addControllersUpdateListener: function () { + this.el.sceneEl.addEventListener('controllersupdated', this.onControllersUpdate, false); + }, + removeControllersUpdateListener: function () { + this.el.sceneEl.removeEventListener('controllersupdated', this.onControllersUpdate, false); + }, + onControllersUpdate: function () { + // Note that due to gamepadconnected event propagation issues, we don't rely on events. + this.checkIfControllerPresent(); + }, + onButtonChanged: function (evt) { + var button = this.mapping[this.data.hand].buttons[evt.detail.id]; + if (!button) { + return; + } + // move the button meshes + if (this.isOculusTouchV3) { + this.onButtonChangedV3(evt); + } else { + var buttonMeshes = this.buttonMeshes; + var analogValue; + if (button === 'trigger' || button === 'grip') { + analogValue = evt.detail.state.value; + } + if (buttonMeshes) { + if (button === 'trigger' && buttonMeshes.trigger) { + buttonMeshes.trigger.rotation.x = this.originalXRotationTrigger - analogValue * (Math.PI / 26); + } + if (button === 'grip' && buttonMeshes.grip) { + analogValue *= this.data.hand === 'left' ? -1 : 1; + buttonMeshes.grip.position.x = this.originalXPositionGrip + analogValue * 0.004; + } + } + } + // Pass along changed event with button state, using the buttom mapping for convenience. + this.el.emit(button + 'changed', evt.detail.state); + }, + clickButtons: ['xbutton', 'ybutton', 'abutton', 'bbutton', 'thumbstick'], + onButtonChangedV3: function (evt) { + var button = this.mapping[this.data.hand].buttons[evt.detail.id]; + var buttonObjects = this.buttonObjects; + var analogValue; + analogValue = evt.detail.state.value; + analogValue *= this.data.hand === 'left' ? -1 : 1; + if (button === 'trigger') { + this.triggerEuler.copy(this.buttonRanges.trigger.min.rotation); + this.triggerEuler.x += analogValue * this.buttonRanges.trigger.diff.x; + this.triggerEuler.y += analogValue * this.buttonRanges.trigger.diff.y; + this.triggerEuler.z += analogValue * this.buttonRanges.trigger.diff.z; + buttonObjects.trigger.setRotationFromEuler(this.triggerEuler); + } else if (button === 'grip') { + buttonObjects.grip.position.x = buttonObjects.grip.minX + analogValue * 0.004; + } else if (this.clickButtons.includes(button)) { + buttonObjects[button].position.y = analogValue === 0 ? this.buttonRanges[button].unpressedY : this.buttonRanges[button].pressedY; + } + }, + onModelLoaded: function (evt) { + if (!this.data.model) { + return; + } + if (this.isOculusTouchV3) { + this.onOculusTouchV3ModelLoaded(evt); + } else { + // All oculus headset controller models prior to the Quest 2 (i.e., Oculus Touch V3) + // used a consistent format that is handled here + var controllerObject3D = this.controllerObject3D = evt.detail.model; + var buttonMeshes; + buttonMeshes = this.buttonMeshes = {}; + buttonMeshes.grip = controllerObject3D.getObjectByName('buttonHand'); + this.originalXPositionGrip = buttonMeshes.grip && buttonMeshes.grip.position.x; + buttonMeshes.trigger = controllerObject3D.getObjectByName('buttonTrigger'); + this.originalXRotationTrigger = buttonMeshes.trigger && buttonMeshes.trigger.rotation.x; + buttonMeshes.thumbstick = controllerObject3D.getObjectByName('stick'); + buttonMeshes.xbutton = controllerObject3D.getObjectByName('buttonX'); + buttonMeshes.abutton = controllerObject3D.getObjectByName('buttonA'); + buttonMeshes.ybutton = controllerObject3D.getObjectByName('buttonY'); + buttonMeshes.bbutton = controllerObject3D.getObjectByName('buttonB'); + } + for (var button in this.buttonMeshes) { + if (this.buttonMeshes[button]) { + cloneMeshMaterial(this.buttonMeshes[button]); + } + } + this.applyOffset(evt.detail.model); + this.el.emit('controllermodelready', { + name: 'oculus-touch-controls', + model: this.data.model, + rayOrigin: this.displayModel[this.data.hand].rayOrigin + }); + }, + applyOffset: function (model) { + model.position.copy(this.displayModel[this.data.hand].modelPivotOffset); + model.rotation.copy(this.displayModel[this.data.hand].modelPivotRotation); + }, + onOculusTouchV3ModelLoaded: function (evt) { + var controllerObject3D = this.controllerObject3D = evt.detail.model; + var buttonObjects = this.buttonObjects = {}; + var buttonMeshes = this.buttonMeshes = {}; + var buttonRanges = this.buttonRanges = {}; + buttonMeshes.grip = controllerObject3D.getObjectByName('squeeze'); + buttonObjects.grip = controllerObject3D.getObjectByName('xr_standard_squeeze_pressed_value'); + buttonRanges.grip = { + min: controllerObject3D.getObjectByName('xr_standard_squeeze_pressed_min'), + max: controllerObject3D.getObjectByName('xr_standard_squeeze_pressed_max') + }; + buttonObjects.grip.minX = buttonObjects.grip.position.x; + buttonMeshes.thumbstick = controllerObject3D.getObjectByName('thumbstick'); + buttonObjects.thumbstick = controllerObject3D.getObjectByName('xr_standard_thumbstick_pressed_value'); + buttonRanges.thumbstick = { + min: controllerObject3D.getObjectByName('xr_standard_thumbstick_pressed_min'), + max: controllerObject3D.getObjectByName('xr_standard_thumbstick_pressed_max'), + originalRotation: this.buttonObjects.thumbstick.rotation.clone() + }; + buttonRanges.thumbstick.pressedY = buttonObjects.thumbstick.position.y; + buttonRanges.thumbstick.unpressedY = buttonRanges.thumbstick.pressedY + Math.abs(buttonRanges.thumbstick.max.position.y) - Math.abs(buttonRanges.thumbstick.min.position.y); + buttonMeshes.trigger = controllerObject3D.getObjectByName('trigger'); + buttonObjects.trigger = controllerObject3D.getObjectByName('xr_standard_trigger_pressed_value'); + buttonRanges.trigger = { + min: controllerObject3D.getObjectByName('xr_standard_trigger_pressed_min'), + max: controllerObject3D.getObjectByName('xr_standard_trigger_pressed_max') + }; + buttonRanges.trigger.diff = { + x: Math.abs(buttonRanges.trigger.max.rotation.x) - Math.abs(buttonRanges.trigger.min.rotation.x), + y: Math.abs(buttonRanges.trigger.max.rotation.y) - Math.abs(buttonRanges.trigger.min.rotation.y), + z: Math.abs(buttonRanges.trigger.max.rotation.z) - Math.abs(buttonRanges.trigger.min.rotation.z) + }; + var button1 = this.data.hand === 'left' ? 'x' : 'a'; + var button2 = this.data.hand === 'left' ? 'y' : 'b'; + var button1id = button1 + 'button'; + var button2id = button2 + 'button'; + buttonMeshes[button1id] = controllerObject3D.getObjectByName(button1 + '_button'); + buttonObjects[button1id] = controllerObject3D.getObjectByName(button1 + '_button_pressed_value'); + buttonRanges[button1id] = { + min: controllerObject3D.getObjectByName(button1 + '_button_pressed_min'), + max: controllerObject3D.getObjectByName(button1 + '_button_pressed_max') + }; + buttonMeshes[button2id] = controllerObject3D.getObjectByName(button2 + '_button'); + buttonObjects[button2id] = controllerObject3D.getObjectByName(button2 + '_button_pressed_value'); + buttonRanges[button2id] = { + min: controllerObject3D.getObjectByName(button2 + '_button_pressed_min'), + max: controllerObject3D.getObjectByName(button2 + '_button_pressed_max') + }; + buttonRanges[button1id].unpressedY = buttonObjects[button1id].position.y; + buttonRanges[button1id].pressedY = buttonRanges[button1id].unpressedY + Math.abs(buttonRanges[button1id].max.position.y) - Math.abs(buttonRanges[button1id].min.position.y); + buttonRanges[button2id].unpressedY = buttonObjects[button2id].position.y; + buttonRanges[button2id].pressedY = buttonRanges[button2id].unpressedY - Math.abs(buttonRanges[button2id].max.position.y) + Math.abs(buttonRanges[button2id].min.position.y); + }, + onAxisMoved: function (evt) { + emitIfAxesChanged(this, this.mapping[this.data.hand].axes, evt); + }, + onThumbstickMoved: function (evt) { + if (!this.isOculusTouchV3 || !this.buttonMeshes || !this.buttonMeshes.thumbstick) { + return; + } + for (var axis in evt.detail) { + this.buttonObjects.thumbstick.rotation[this.axisMap[axis]] = this.buttonRanges.thumbstick.originalRotation[this.axisMap[axis]] - Math.PI / 8 * evt.detail[axis] * (axis === 'y' || this.data.hand === 'right' ? -1 : 1); + } + }, + axisMap: { + y: 'x', + x: 'z' + }, + updateModel: function (buttonName, evtName) { + if (!this.data.model) { + return; + } + this.updateButtonModel(buttonName, evtName); + }, + updateButtonModel: function (buttonName, state) { + // update the button mesh colors + var button; + var color = state === 'up' || state === 'touchend' ? this.buttonMeshes[buttonName].originalColor || this.data.buttonColor : state === 'touchstart' ? this.data.buttonTouchColor : this.data.buttonHighlightColor; + var buttonMeshes = this.buttonMeshes; + if (buttonMeshes && buttonMeshes[buttonName]) { + button = buttonMeshes[buttonName]; + button.material.color.set(color); + this.rendererSystem.applyColorCorrection(button.material.color); + } + } +}); + +/** + * Some of the controller models share the same material for different parts (buttons, triggers...). + * In order to change their color independently we have to create separate materials. + */ +function cloneMeshMaterial(object3d) { + object3d.traverse(function (node) { + if (node.type !== 'Mesh') return; + let newMaterial = node.material.clone(); + object3d.originalColor = node.material.color; + node.material.dispose(); + node.material = newMaterial; + }); +} + +/***/ }), + +/***/ "./src/components/position.js": +/*!************************************!*\ + !*** ./src/components/position.js ***! + \************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +module.exports.Component = registerComponent('position', { + schema: { + type: 'vec3' + }, + update: function () { + var object3D = this.el.object3D; + var data = this.data; + object3D.position.set(data.x, data.y, data.z); + }, + remove: function () { + // Pretty much for mixins. + this.el.object3D.position.set(0, 0, 0); + } +}); + +/***/ }), + +/***/ "./src/components/raycaster.js": +/*!*************************************!*\ + !*** ./src/components/raycaster.js ***! + \*************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/* global MutationObserver */ + +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var THREE = __webpack_require__(/*! ../lib/three */ "./src/lib/three.js"); +var utils = __webpack_require__(/*! ../utils/ */ "./src/utils/index.js"); +var warn = utils.debug('components:raycaster:warn'); + +// Defines selectors that should be 'safe' for the MutationObserver used to +// refresh the whitelist. Matches classnames, IDs, and presence of attributes. +// Selectors for the value of an attribute, like [position=0 2 0], cannot be +// reliably detected and are therefore disallowed. +var OBSERVER_SELECTOR_RE = /^[\w\s-.,[\]#]*$/; + +// Configuration for the MutationObserver used to refresh the whitelist. +// Listens for addition/removal of elements and attributes within the scene. +var OBSERVER_CONFIG = { + childList: true, + attributes: true, + subtree: true +}; +var EVENTS = { + INTERSECT: 'raycaster-intersected', + INTERSECTION: 'raycaster-intersection', + INTERSECT_CLEAR: 'raycaster-intersected-cleared', + INTERSECTION_CLEAR: 'raycaster-intersection-cleared', + INTERSECTION_CLOSEST_ENTITY_CHANGED: 'raycaster-closest-entity-changed' +}; + +/** + * Raycaster component. + * + * Pass options to three.js Raycaster including which objects to test. + * Poll for intersections. + * Emit event on origin entity and on target entity on intersect. + * + * @member {array} intersectedEls - List of currently intersected entities. + * @member {array} objects - Cached list of meshes to intersect. + * @member {number} prevCheckTime - Previous time intersection was checked. To help interval. + * @member {object} raycaster - three.js Raycaster. + */ +module.exports.Component = registerComponent('raycaster', { + schema: { + autoRefresh: { + default: true + }, + direction: { + type: 'vec3', + default: { + x: 0, + y: 0, + z: -1 + } + }, + enabled: { + default: true + }, + far: { + default: 1000 + }, + interval: { + default: 0 + }, + near: { + default: 0 + }, + objects: { + default: '' + }, + origin: { + type: 'vec3' + }, + showLine: { + default: false + }, + lineColor: { + default: 'white' + }, + lineOpacity: { + default: 1 + }, + useWorldCoordinates: { + default: false + } + }, + multiple: true, + init: function () { + this.clearedIntersectedEls = []; + this.unitLineEndVec3 = new THREE.Vector3(); + this.intersectedEls = []; + this.intersections = []; + this.newIntersectedEls = []; + this.newIntersections = []; + this.objects = []; + this.prevCheckTime = undefined; + this.prevIntersectedEls = []; + this.rawIntersections = []; + this.raycaster = new THREE.Raycaster(); + this.updateOriginDirection(); + this.setDirty = this.setDirty.bind(this); + this.updateLine = this.updateLine.bind(this); + this.observer = new MutationObserver(this.setDirty); + this.dirty = true; + this.lineEndVec3 = new THREE.Vector3(); + this.otherLineEndVec3 = new THREE.Vector3(); + this.lineData = { + end: this.lineEndVec3 + }; + this.getIntersection = this.getIntersection.bind(this); + this.intersectedDetail = { + el: this.el, + getIntersection: this.getIntersection + }; + this.intersectedClearedDetail = { + el: this.el + }; + this.intersectionClearedDetail = { + clearedEls: this.clearedIntersectedEls + }; + this.intersectionDetail = {}; + }, + /** + * Create or update raycaster object. + */ + update: function (oldData) { + var data = this.data; + var el = this.el; + var raycaster = this.raycaster; + + // Set raycaster properties. + raycaster.far = data.far; + raycaster.near = data.near; + + // Draw line. + if (data.showLine && (data.far !== oldData.far || data.origin !== oldData.origin || data.direction !== oldData.direction || !oldData.showLine)) { + // Calculate unit vector for line direction. Can be multiplied via scalar to performantly + // adjust line length. + this.unitLineEndVec3.copy(data.origin).add(data.direction).normalize(); + this.drawLine(); + } + if (!data.showLine && oldData.showLine) { + el.removeAttribute('line'); + } + if (data.objects !== oldData.objects && !OBSERVER_SELECTOR_RE.test(data.objects)) { + warn('[raycaster] Selector "' + data.objects + '" may not update automatically with DOM changes.'); + } + if (!data.objects) { + warn('[raycaster] For performance, please define raycaster.objects when using ' + 'raycaster or cursor components to whitelist which entities to intersect with. ' + 'e.g., raycaster="objects: [data-raycastable]".'); + } + if (data.autoRefresh !== oldData.autoRefresh && el.isPlaying) { + data.autoRefresh ? this.addEventListeners() : this.removeEventListeners(); + } + if (oldData.enabled && !data.enabled) { + this.clearAllIntersections(); + } + this.setDirty(); + }, + play: function () { + this.addEventListeners(); + }, + pause: function () { + this.removeEventListeners(); + }, + remove: function () { + if (this.data.showLine) { + this.el.removeAttribute('line'); + } + this.clearAllIntersections(); + }, + addEventListeners: function () { + if (!this.data.autoRefresh) { + return; + } + this.observer.observe(this.el.sceneEl, OBSERVER_CONFIG); + this.el.sceneEl.addEventListener('object3dset', this.setDirty); + this.el.sceneEl.addEventListener('object3dremove', this.setDirty); + }, + removeEventListeners: function () { + this.observer.disconnect(); + this.el.sceneEl.removeEventListener('object3dset', this.setDirty); + this.el.sceneEl.removeEventListener('object3dremove', this.setDirty); + }, + /** + * Mark the object list as dirty, to be refreshed before next raycast. + */ + setDirty: function () { + this.dirty = true; + }, + /** + * Update list of objects to test for intersection. + */ + refreshObjects: function () { + var data = this.data; + var els; + + // If objects not defined, intersect with everything. + els = data.objects ? this.el.sceneEl.querySelectorAll(data.objects) : this.el.sceneEl.querySelectorAll('*'); + this.objects = this.flattenObject3DMaps(els); + this.dirty = false; + }, + /** + * Check for intersections and cleared intersections on an interval. + */ + tock: function (time) { + var data = this.data; + var prevCheckTime = this.prevCheckTime; + if (!data.enabled) { + return; + } + + // Only check for intersection if interval time has passed. + if (prevCheckTime && time - prevCheckTime < data.interval) { + return; + } + + // Update check time. + this.prevCheckTime = time; + this.checkIntersections(); + }, + /** + * Raycast for intersections and emit events for current and cleared intersections. + */ + checkIntersections: function () { + var clearedIntersectedEls = this.clearedIntersectedEls; + var el = this.el; + var data = this.data; + var i; + var intersectedEls = this.intersectedEls; + var intersection; + var intersections = this.intersections; + var newIntersectedEls = this.newIntersectedEls; + var newIntersections = this.newIntersections; + var prevIntersectedEls = this.prevIntersectedEls; + var rawIntersections = this.rawIntersections; + + // Refresh the object whitelist if needed. + if (this.dirty) { + this.refreshObjects(); + } + + // Store old previously intersected entities. + copyArray(this.prevIntersectedEls, this.intersectedEls); + + // Raycast. + this.updateOriginDirection(); + rawIntersections.length = 0; + this.raycaster.intersectObjects(this.objects, true, rawIntersections); + + // Only keep intersections against objects that have a reference to an entity. + intersections.length = 0; + intersectedEls.length = 0; + for (i = 0; i < rawIntersections.length; i++) { + intersection = rawIntersections[i]; + // Don't intersect with own line. + if (data.showLine && intersection.object === el.getObject3D('line')) { + continue; + } + if (intersection.object.el) { + intersections.push(intersection); + intersectedEls.push(intersection.object.el); + } + } + + // Get newly intersected entities. + newIntersections.length = 0; + newIntersectedEls.length = 0; + for (i = 0; i < intersections.length; i++) { + if (prevIntersectedEls.indexOf(intersections[i].object.el) === -1) { + newIntersections.push(intersections[i]); + newIntersectedEls.push(intersections[i].object.el); + } + } + + // Emit intersection cleared on both entities per formerly intersected entity. + clearedIntersectedEls.length = 0; + for (i = 0; i < prevIntersectedEls.length; i++) { + if (intersectedEls.indexOf(prevIntersectedEls[i]) !== -1) { + continue; + } + prevIntersectedEls[i].emit(EVENTS.INTERSECT_CLEAR, this.intersectedClearedDetail); + clearedIntersectedEls.push(prevIntersectedEls[i]); + } + if (clearedIntersectedEls.length) { + el.emit(EVENTS.INTERSECTION_CLEAR, this.intersectionClearedDetail); + } + + // Emit intersected on intersected entity per intersected entity. + for (i = 0; i < newIntersectedEls.length; i++) { + newIntersectedEls[i].emit(EVENTS.INTERSECT, this.intersectedDetail); + } + + // Emit all intersections at once on raycasting entity. + if (newIntersections.length) { + this.intersectionDetail.els = newIntersectedEls; + this.intersectionDetail.intersections = newIntersections; + el.emit(EVENTS.INTERSECTION, this.intersectionDetail); + } + + // Emit event when the closest intersected entity has changed. + if (prevIntersectedEls.length === 0 && intersections.length > 0 || prevIntersectedEls.length > 0 && intersections.length === 0 || prevIntersectedEls.length && intersections.length && prevIntersectedEls[0] !== intersections[0].object.el) { + this.intersectionDetail.els = this.intersectedEls; + this.intersectionDetail.intersections = intersections; + el.emit(EVENTS.INTERSECTION_CLOSEST_ENTITY_CHANGED, this.intersectionDetail); + } + + // Update line length. + if (data.showLine) { + setTimeout(this.updateLine); + } + }, + updateLine: function () { + var el = this.el; + var intersections = this.intersections; + var lineLength; + if (intersections.length) { + if (intersections[0].object.el === el && intersections[1]) { + lineLength = intersections[1].distance; + } else { + lineLength = intersections[0].distance; + } + } + this.drawLine(lineLength); + }, + /** + * Return the most recent intersection details for a given entity, if any. + * @param {AEntity} el + * @return {Object} + */ + getIntersection: function (el) { + var i; + var intersection; + for (i = 0; i < this.intersections.length; i++) { + intersection = this.intersections[i]; + if (intersection.object.el === el) { + return intersection; + } + } + return null; + }, + /** + * Update origin and direction of raycaster using entity transforms and supplied origin or + * direction offsets. + */ + updateOriginDirection: function () { + var direction = new THREE.Vector3(); + var originVec3 = new THREE.Vector3(); + + // Closure to make quaternion/vector3 objects private. + return function updateOriginDirection() { + var el = this.el; + var data = this.data; + if (data.useWorldCoordinates) { + this.raycaster.set(data.origin, data.direction); + return; + } + el.object3D.updateMatrixWorld(); + originVec3.setFromMatrixPosition(el.object3D.matrixWorld); + + // If non-zero origin, translate the origin into world space. + if (data.origin.x !== 0 || data.origin.y !== 0 || data.origin.z !== 0) { + originVec3 = el.object3D.localToWorld(originVec3.copy(data.origin)); + } + + // three.js raycaster direction is relative to 0, 0, 0 NOT the origin / offset we + // provide. Apply the offset to the direction, then rotation from the object, + // and normalize. + direction.copy(data.direction).transformDirection(el.object3D.matrixWorld).normalize(); + + // Apply offset and direction, in world coordinates. + this.raycaster.set(originVec3, direction); + }; + }(), + /** + * Create or update line to give raycaster visual representation. + * Customize the line through through line component. + * We draw the line in the raycaster component to customize the line to the + * raycaster's origin, direction, and far. + * + * Unlike the raycaster, we create the line as a child of the object. The line will + * be affected by the transforms of the objects, so we don't have to calculate transforms + * like we do with the raycaster. + * + * @param {number} length - Length of line. Pass in to shorten the line to the intersection + * point. If not provided, length will default to the max length, `raycaster.far`. + */ + drawLine: function (length) { + var data = this.data; + var el = this.el; + var endVec3; + + // Switch each time vector so line update triggered and to avoid unnecessary vector clone. + endVec3 = this.lineData.end === this.lineEndVec3 ? this.otherLineEndVec3 : this.lineEndVec3; + + // Treat Infinity as 1000m for the line. + if (length === undefined) { + length = data.far === Infinity ? 1000 : data.far; + } + + // Update the length of the line if given. `unitLineEndVec3` is the direction + // given by data.direction, then we apply a scalar to give it a length. + this.lineData.start = data.origin; + this.lineData.end = endVec3.copy(this.unitLineEndVec3).multiplyScalar(length); + this.lineData.color = data.lineColor; + this.lineData.opacity = data.lineOpacity; + el.setAttribute('line', this.lineData); + }, + /** + * Return A-Frame attachments of each element's object3D group (e.g., mesh). + * Children are flattened by one level, removing the THREE.Group wrapper, + * so that non-recursive raycasting remains useful. + * + * Only push children defined as component attachements (e.g., setObject3D), + * NOT actual children in the scene graph hierarchy. + * + * @param {Array} els + * @return {Array} + */ + flattenObject3DMaps: function (els) { + var key; + var i; + var objects = this.objects; + var scene = this.el.sceneEl.object3D; + function isAttachedToScene(object) { + if (object.parent) { + return isAttachedToScene(object.parent); + } else { + return object === scene; + } + } + + // Push meshes and other attachments onto list of objects to intersect. + objects.length = 0; + for (i = 0; i < els.length; i++) { + var el = els[i]; + if (el.isEntity && el.object3D && isAttachedToScene(el.object3D)) { + for (key in el.object3DMap) { + objects.push(el.getObject3D(key)); + } + } + } + return objects; + }, + clearAllIntersections: function () { + var i; + for (i = 0; i < this.intersectedEls.length; i++) { + this.intersectedEls[i].emit(EVENTS.INTERSECT_CLEAR, this.intersectedClearedDetail); + } + copyArray(this.clearedIntersectedEls, this.intersectedEls); + this.intersectedEls.length = 0; + this.intersections.length = 0; + this.el.emit(EVENTS.INTERSECTION_CLEAR, this.intersectionClearedDetail); + } +}); + +/** + * Copy contents of one array to another without allocating new array. + */ +function copyArray(a, b) { + var i; + a.length = b.length; + for (i = 0; i < b.length; i++) { + a[i] = b[i]; + } +} + +/***/ }), + +/***/ "./src/components/rotation.js": +/*!************************************!*\ + !*** ./src/components/rotation.js ***! + \************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var degToRad = (__webpack_require__(/*! ../lib/three */ "./src/lib/three.js").MathUtils.degToRad); +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +module.exports.Component = registerComponent('rotation', { + schema: { + type: 'vec3' + }, + /** + * Updates object3D rotation. + */ + update: function () { + var data = this.data; + var object3D = this.el.object3D; + object3D.rotation.set(degToRad(data.x), degToRad(data.y), degToRad(data.z)); + object3D.rotation.order = 'YXZ'; + }, + remove: function () { + // Pretty much for mixins. + this.el.object3D.rotation.set(0, 0, 0); + } +}); + +/***/ }), + +/***/ "./src/components/scale.js": +/*!*********************************!*\ + !*** ./src/components/scale.js ***! + \*********************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); + +// Avoids triggering a zero-determinant which makes object3D matrix non-invertible. +var zeroScale = 0.00001; +module.exports.Component = registerComponent('scale', { + schema: { + type: 'vec3', + default: { + x: 1, + y: 1, + z: 1 + } + }, + update: function () { + var data = this.data; + var object3D = this.el.object3D; + var x = data.x === 0 ? zeroScale : data.x; + var y = data.y === 0 ? zeroScale : data.y; + var z = data.z === 0 ? zeroScale : data.z; + object3D.scale.set(x, y, z); + }, + remove: function () { + // Pretty much for mixins. + this.el.object3D.scale.set(1, 1, 1); + } +}); + +/***/ }), + +/***/ "./src/components/scene/ar-hit-test.js": +/*!*********************************************!*\ + !*** ./src/components/scene/ar-hit-test.js ***! + \*********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/* global ImageData, Map, Set */ +var arrowURL = 'data:image/webp;base64,UklGRkQHAABXRUJQVlA4WAoAAAAQAAAA/wEA/wEAQUxQSL0DAAARDzD/ERGCjrY9sYYFfgo6aa1kJ7K0w9Lo3AadLSVeFxevQwj5kuM8RfR/Atw/C0+ozB/oUBrloFZs6ElSW88j1KA4yExNWQaqRZquIDF0JYmlq0hAuUDTFu66tng3teW7pa3cQf1V1edvur54M/Slm6Wv3Gx9zw0MXlQLntcsBN6wkHjTQuYtC4W3LTw8mGRVG57TbAROtxHfZNhInGkjc5aNwtk2Hg6Mvki14k+NkZzCwQgCxalcAv3kddRTPI1DcUrXId1FLf1uHpzaQz4tquhZVLlKesbVpqKeTj0n0F5PpXDlFN9UqmhalL/ImuZFo6KmToWLoKlddMprqlS8cKovBvHo2kTiFV2LN4msaxKZl3QNiair8xYRdDWivIvXVXmbcMqJ51UebZuFXxZt6xd4laxtciqRtA3Cv0nU1t+kEUFbI8JvCa+tvkm3FDlO/W+OR99+kWEp/YYo+tYfTVnf/K8cE/F///3vv//993eeL+a+uvjawLcX3xjYvJotBFY3kVjTRGFtE+BU2AiMbiQyhpHMWEYeBozAH5qNBYRDB5KBCaTDBKKBAZTDBoKBDjwHAN5ABeCJBsAZcAAC0YHHxAYSMYBiYgGZWEA2MYFCbCCZGAAIANFEB+AnYgMQTDQAYSJ2AN5EBZAm4gDgTDgAeSIu4DGygTIRN1CMLOCZiACykQlg4jsAycgA8AO+BxCNdJyDkcbwRirDGXGnx8w+FDPrkM3MQ9JQZMYhiiwV/RDMtIM3U1/DmXHUo+IR2kSR2ToWkQ1NIn2qf2J8LCqJKiDUiSADHY3whirhdHgZ94HKaR97PhE+twEUJUFoAcgyTct8hfSxSkShASDKdMJ/ritKHwgyQ0sD4D/miCxU5SbhOOUDTnZpccCjYP/i0bZ/8bAgtVGEoGapWIQXyzKVKLwgNJFk2rtMIgoNRJlOZF7SNSSyUEeQmbxBFKEmtYjEe8S8zOZ1AkJVCmS88FJOtF40Ksg4oUaFiygk3C8qlTVNyl8UTevCUdAE2t14PfVqU1FPp57TopKeQZWromddTQp6QOfTOEQt/ZDuipZ11w/wOiqO8dRORcc6BQEkDQMClaHcn5wV9yLbxsNZNgpn2sicYSNxuo34Js1G4FQbnuNsOPa28PCWhcKbFjJvWEi8ZiHwqgXPcxbc5db33Cx95WboSzddX7yp+vyN0+eul7ZyN7Xlu64t3jVt4c5pc4JLV5EYupJE0xUknC4nOjVlmaYpyLit53HCQ0+ScnqceNcS5dzUkd0/CwMAVlA4IGADAAAQXwCdASoAAgACP8ne6Wy/tjCpqJ/IA/A5CWlu4XYBG/Pz8AfwD8APz//f3v8E1fuHZnxKYACtfuHZnxKYACrYTb5mOslhxu843ecbvON3nG7zjd3a0VCn7G1MABVxwH/Xd25gAK1+4dmfEpe2+PHhQaj75++riG6FuYACtfuHZnxKYACRrK3q9xO8Ss3uWKnMhs/rDF1hi6wxdYYusMXWGI5QRcCFDZog5OgqNlse1NDuz/UoFa/cOzPiUwAEsAOK4/nu5eZHK2tlXxJfNYlMABWv3Dsz4bvNJ5YA/LtxJ38SmAArX7h2Z8Sk5vdZUYv7mZPiUwAFa/cOzPh21s5OgZxf1mfEpemRyFr/rM+JS9noA/LtxJ38SmAAlUJIotzAASn6TjdhK+D3Dsz4dyvB7h2Z8O2tnJ0DOL+sz4lL2nKLT4lL/+iSLOocxq639w7M34MNZdm55uJ8v8ra2cpVZnxKTq2F3PN/cNksAfl24k7+JTAASqrD37h2Z7b1W+VtbOUqsz4lJ1bC7nm/uGyWAPy7cSd/EpgAJVVh79w7M9t6rfK2tnKVWZ8Sk6thdzzf3DZLAH5duJO/iUwAEqqw9+4dme29VvlbWzlKrM+JSdWwu55v7hslgD8u3EnfxKYACVVYe/cOzPbeq3ytrZylVme0kYJ8557FLerqFrzIbPrrf3DZLAH5duJO/iUvaVMS9BoaF4p7pSDFTP1XMyfElelrM0DOL+sz4eBJ13nV1OppBGPuKb4YzXQgq9uH19uS/0+JS9t9fr6ZUlQBelDG6GMgq97otb5QMPJwtKyBTbFp8Sl7b6/X0ykkawEOsgdiE6Fi0vb/Eve6xkwsmug0Z4nGNHQO8839bpTsjpz7SWIJxKagvd1QWMa6FYT1KEw3j4XDT6vJ9Xk+nyfT5Pq8n1eEmk5dinMM/9Fcfz4Z3Dsz3KD2dw7LxBRxKrqUUGQPH/7zxr1KIfNpLEJ0MZB2ITM/0Z2EFoh12NlXnEcpYcbvON3nG7zjd5xu84vfcNIAAP7+y8ceyzbVxkakPYY4lcr72fqOnDwipv+yxC71wAADBrjKnAAAAAAAAAAAAAAw7oNGHttqWONcoFN/2WIDc2pa6WVFtFYROlsaMaTXdcOjXHz93+YxAglKa4AAAAA='; +var register = (__webpack_require__(/*! ../../core/component */ "./src/core/component.js").registerComponent); +var THREE = __webpack_require__(/*! ../../lib/three */ "./src/lib/three.js"); +var CAM_LAYER = 21; +var applyPose = function () { + var tempQuaternion = new THREE.Quaternion(); + var tempVec3 = new THREE.Vector3(); + function applyPose(pose, object3D, offset) { + object3D.position.copy(pose.transform.position); + object3D.quaternion.copy(pose.transform.orientation); + tempVec3.copy(offset); + tempQuaternion.copy(pose.transform.orientation); + tempVec3.applyQuaternion(tempQuaternion); + object3D.position.sub(tempVec3); + } + return applyPose; +}(); +applyPose.tempFakePose = { + transform: { + orientation: new THREE.Quaternion(), + position: new THREE.Vector3() + } +}; + +/** + * Class to handle hit-test from a single source + * + * For a normal space provide it as a space option + * new HitTest(renderer, { + * space: viewerSpace + * }); + * + * this is also useful for the targetRaySpace of an XRInputSource + * + * It can also describe a transient input source like so: + * + * var profileToSupport = 'generic-touchscreen'; + * var transientHitTest = new HitTest(renderer, { + * profile: profileToSupport + * }); + * + * Where the profile matches an item in a type of controller, profiles matching 'generic-touchscreen' + * will always be a transient input and as of 08/2021 all transient inputs are 'generic-touchscreen' + * + * @param {WebGLRenderer} renderer THREE.JS Renderer + * @param {} hitTestSourceDetails The source information either as the information for a transient hit-test or a regular hit-test + */ +function HitTest(renderer, hitTestSourceDetails) { + this.renderer = renderer; + this.xrHitTestSource = null; + renderer.xr.addEventListener('sessionend', function () { + this.xrHitTestSource = null; + }.bind(this)); + renderer.xr.addEventListener('sessionstart', function () { + this.sessionStart(hitTestSourceDetails); + }.bind(this)); + if (this.renderer.xr.isPresenting) { + this.sessionStart(hitTestSourceDetails); + } +} +HitTest.prototype.previousFrameAnchors = new Set(); +HitTest.prototype.anchorToObject3D = new Map(); +function warnAboutHitTest(e) { + console.warn(e.message); + console.warn('Cannot requestHitTestSource Are you missing: webxr="optionalFeatures: hit-test;" from ?'); +} +HitTest.prototype.sessionStart = function sessionStart(hitTestSourceDetails) { + this.session = this.renderer.xr.getSession(); + if (!('requestHitTestSource' in this.session)) { + warnAboutHitTest({ + message: 'No requestHitTestSource on the session.' + }); + return; + } + if (hitTestSourceDetails.space) { + this.session.requestHitTestSource(hitTestSourceDetails).then(function (xrHitTestSource) { + this.xrHitTestSource = xrHitTestSource; + }.bind(this)).catch(warnAboutHitTest); + } else if (hitTestSourceDetails.profile) { + this.session.requestHitTestSourceForTransientInput(hitTestSourceDetails).then(function (xrHitTestSource) { + this.xrHitTestSource = xrHitTestSource; + this.transient = true; + }.bind(this)).catch(warnAboutHitTest); + } +}; + +/** + * Turns the last hit test into an anchor, the provided Object3D will have it's + * position update to track the anchor. + * + * @param {Object3D} object3D object to track + * @param {Vector3} offset offset of the object from the origin that gets subtracted + * @returns + */ +HitTest.prototype.anchorFromLastHitTestResult = function (object3D, offset) { + var hitTest = this.lastHitTest; + if (!hitTest) { + return; + } + var object3DOptions = { + object3D: object3D, + offset: offset + }; + Array.from(this.anchorToObject3D.entries()).forEach(function (entry) { + var entryObject = entry[1].object3D; + var anchor = entry[0]; + if (entryObject === object3D) { + this.anchorToObject3D.delete(anchor); + anchor.delete(); + } + }.bind(this)); + if (hitTest.createAnchor) { + hitTest.createAnchor().then(function (anchor) { + this.anchorToObject3D.set(anchor, object3DOptions); + }.bind(this)).catch(function (e) { + console.warn(e.message); + console.warn('Cannot create anchor, are you missing: webxr="optionalFeatures: anchors;" from ?'); + }); + } +}; +HitTest.prototype.doHit = function doHit(frame) { + if (!this.renderer.xr.isPresenting) { + return; + } + var refSpace = this.renderer.xr.getReferenceSpace(); + var xrViewerPose = frame.getViewerPose(refSpace); + var hitTestResults; + var results; + if (this.xrHitTestSource && xrViewerPose) { + if (this.transient) { + hitTestResults = frame.getHitTestResultsForTransientInput(this.xrHitTestSource); + if (hitTestResults.length > 0) { + results = hitTestResults[0].results; + if (results.length > 0) { + this.lastHitTest = results[0]; + return results[0].getPose(refSpace); + } else { + return false; + } + } else { + return false; + } + } else { + hitTestResults = frame.getHitTestResults(this.xrHitTestSource); + if (hitTestResults.length > 0) { + this.lastHitTest = hitTestResults[0]; + return hitTestResults[0].getPose(refSpace); + } else { + return false; + } + } + } +}; + +// static function +HitTest.updateAnchorPoses = function (frame, refSpace) { + // If tracked anchors isn't defined because it's not supported then just use the empty set + var trackedAnchors = frame.trackedAnchors || HitTest.prototype.previousFrameAnchors; + HitTest.prototype.previousFrameAnchors.forEach(function (anchor) { + // Handle anchor tracking loss - `anchor` was present + // in the present frame but is no longer tracked. + if (!trackedAnchors.has(anchor)) { + HitTest.prototype.anchorToObject3D.delete(anchor); + } + }); + trackedAnchors.forEach(function (anchor) { + var anchorPose; + var object3DOptions; + var offset; + var object3D; + try { + // Query most recent pose of the anchor relative to some reference space: + anchorPose = frame.getPose(anchor.anchorSpace, refSpace); + } catch (e) { + // This will fail if the anchor has been deleted that frame + } + if (anchorPose) { + object3DOptions = HitTest.prototype.anchorToObject3D.get(anchor); + offset = object3DOptions.offset; + object3D = object3DOptions.object3D; + applyPose(anchorPose, object3D, offset); + } + }); +}; +var hitTestCache; +module.exports.Component = register('ar-hit-test', { + schema: { + target: { + type: 'selector' + }, + enabled: { + default: true + }, + src: { + default: arrowURL, + type: 'map' + }, + type: { + default: 'footprint', + oneOf: ['footprint', 'map'] + }, + footprintDepth: { + default: 0.1 + }, + mapSize: { + type: 'vec2', + default: { + x: 0.5, + y: 0.5 + } + } + }, + init: function () { + this.hitTest = null; + this.imageDataArray = new Uint8ClampedArray(512 * 512 * 4); + this.imageData = new ImageData(this.imageDataArray, 512, 512); + this.textureCache = new Map(); + this.orthoCam = new THREE.OrthographicCamera(); + this.orthoCam.layers.set(CAM_LAYER); + this.textureTarget = new THREE.WebGLRenderTarget(512, 512, {}); + this.basicMaterial = new THREE.MeshBasicMaterial({ + color: 0x000000, + side: THREE.DoubleSide + }); + this.canvas = document.createElement('canvas'); + this.context = this.canvas.getContext('2d'); + this.context.imageSmoothingEnabled = false; + this.canvas.width = 512; + this.canvas.height = 512; + this.canvasTexture = new THREE.CanvasTexture(this.canvas, { + alpha: true + }); + this.canvasTexture.flipY = false; + + // Update WebXR to support hit-test and anchors + var webxrData = this.el.getAttribute('webxr'); + var optionalFeaturesArray = webxrData.optionalFeatures; + if (!optionalFeaturesArray.includes('hit-test') || !optionalFeaturesArray.includes('anchors')) { + optionalFeaturesArray.push('hit-test'); + optionalFeaturesArray.push('anchors'); + this.el.setAttribute('webxr', webxrData); + } + this.el.sceneEl.renderer.xr.addEventListener('sessionend', function () { + this.hitTest = null; + }.bind(this)); + this.el.sceneEl.renderer.xr.addEventListener('sessionstart', function () { + // Don't request Hit Test unless AR (breaks WebXR Emulator) + if (!this.el.is('ar-mode')) { + return; + } + var renderer = this.el.sceneEl.renderer; + var session = this.session = renderer.xr.getSession(); + this.hasPosedOnce = false; + this.bboxMesh.visible = false; + if (!hitTestCache) { + hitTestCache = new Map(); + } + + // Default to selecting through the face + session.requestReferenceSpace('viewer').then(function (viewerSpace) { + this.hitTest = new HitTest(renderer, { + space: viewerSpace + }); + hitTestCache.set(viewerSpace, this.hitTest); + this.el.emit('ar-hit-test-start'); + }.bind(this)); + + // These are transient inputs so need to be handled seperately + var profileToSupport = 'generic-touchscreen'; + var transientHitTest = new HitTest(renderer, { + profile: profileToSupport + }); + session.addEventListener('selectstart', function (e) { + if (this.data.enabled !== true) { + return; + } + var inputSource = e.inputSource; + this.bboxMesh.visible = true; + if (this.hasPosedOnce === true) { + this.el.emit('ar-hit-test-select-start', { + inputSource: inputSource, + position: this.bboxMesh.position, + orientation: this.bboxMesh.quaternion + }); + if (inputSource.profiles[0] === profileToSupport) { + this.hitTest = transientHitTest; + } else { + this.hitTest = hitTestCache.get(inputSource) || new HitTest(renderer, { + space: inputSource.targetRaySpace + }); + hitTestCache.set(inputSource, this.hitTest); + } + } + }.bind(this)); + session.addEventListener('selectend', function (e) { + if (!this.hitTest || this.data.enabled !== true) { + this.hitTest = null; + return; + } + var inputSource = e.inputSource; + var object; + if (this.hasPosedOnce === true) { + this.bboxMesh.visible = false; + + // if we have a target with a 3D object then automatically generate an anchor for it. + if (this.data.target) { + object = this.data.target.object3D; + if (object) { + applyPose.tempFakePose.transform.position.copy(this.bboxMesh.position); + applyPose.tempFakePose.transform.orientation.copy(this.bboxMesh.quaternion); + applyPose(applyPose.tempFakePose, object, this.bboxOffset); + object.visible = true; + + // create an anchor attatched to the object + this.hitTest.anchorFromLastHitTestResult(object, this.bboxOffset); + } + } + this.el.emit('ar-hit-test-select', { + inputSource: inputSource, + position: this.bboxMesh.position, + orientation: this.bboxMesh.quaternion + }); + } + this.hitTest = null; + }.bind(this)); + }.bind(this)); + this.bboxOffset = new THREE.Vector3(); + this.update = this.update.bind(this); + this.makeBBox(); + }, + update: function () { + // If it is disabled it's cleaned up + if (this.data.enabled === false) { + this.hitTest = null; + this.bboxMesh.visible = false; + } + if (this.data.target) { + if (this.data.target.object3D) { + this.data.target.addEventListener('model-loaded', this.update); + this.data.target.object3D.layers.enable(CAM_LAYER); + this.data.target.object3D.traverse(function (child) { + child.layers.enable(CAM_LAYER); + }); + } else { + this.data.target.addEventListener('loaded', this.update, { + once: true + }); + } + } + this.bboxNeedsUpdate = true; + }, + makeBBox: function () { + var geometry = new THREE.PlaneGeometry(1, 1); + var material = new THREE.MeshBasicMaterial({ + transparent: true, + color: 0xffffff + }); + geometry.rotateX(-Math.PI / 2); + geometry.rotateY(-Math.PI / 2); + this.bbox = new THREE.Box3(); + this.bboxMesh = new THREE.Mesh(geometry, material); + this.el.setObject3D('ar-hit-test', this.bboxMesh); + this.bboxMesh.visible = false; + }, + updateFootprint: function () { + var tempImageData; + var renderer = this.el.sceneEl.renderer; + var oldRenderTarget, oldBackground; + var isXREnabled = renderer.xr.enabled; + this.bboxMesh.material.map = this.canvasTexture; + this.bboxMesh.material.needsUpdate = true; + this.orthoCam.rotation.set(-Math.PI / 2, 0, -Math.PI / 2); + this.orthoCam.position.copy(this.bboxMesh.position); + this.orthoCam.position.y -= this.bboxMesh.scale.y / 2; + this.orthoCam.near = 0.1; + this.orthoCam.far = this.orthoCam.near + this.data.footprintDepth * this.bboxMesh.scale.y; + this.orthoCam.position.y += this.orthoCam.far; + this.orthoCam.right = this.bboxMesh.scale.z / 2; + this.orthoCam.left = -this.bboxMesh.scale.z / 2; + this.orthoCam.top = this.bboxMesh.scale.x / 2; + this.orthoCam.bottom = -this.bboxMesh.scale.x / 2; + this.orthoCam.updateProjectionMatrix(); + oldRenderTarget = renderer.getRenderTarget(); + renderer.setRenderTarget(this.textureTarget); + renderer.xr.enabled = false; + oldBackground = this.el.object3D.background; + this.el.object3D.overrideMaterial = this.basicMaterial; + this.el.object3D.background = null; + renderer.render(this.el.object3D, this.orthoCam); + this.el.object3D.background = oldBackground; + this.el.object3D.overrideMaterial = null; + renderer.xr.enabled = isXREnabled; + renderer.setRenderTarget(oldRenderTarget); + renderer.readRenderTargetPixels(this.textureTarget, 0, 0, 512, 512, this.imageDataArray); + this.context.putImageData(this.imageData, 0, 0); + this.context.shadowColor = 'white'; + this.context.shadowBlur = 10; + this.context.drawImage(this.canvas, 0, 0); + tempImageData = this.context.getImageData(0, 0, 512, 512); + for (var i = 0; i < 512 * 512; i++) { + // if it's a little bit transparent but not opaque make it middle transparent + if (tempImageData.data[i * 4 + 3] !== 0 && tempImageData.data[i * 4 + 3] !== 255) { + tempImageData.data[i * 4 + 3] = 128; + } + } + this.context.putImageData(tempImageData, 0, 0); + this.canvasTexture.needsUpdate = true; + }, + tick: function () { + var pose; + var frame = this.el.sceneEl.frame; + var renderer = this.el.sceneEl.renderer; + if (frame) { + // if we are in XR then update the positions of the objects attatched to anchors + HitTest.updateAnchorPoses(frame, renderer.xr.getReferenceSpace()); + } + if (this.bboxNeedsUpdate) { + this.bboxNeedsUpdate = false; + if (!this.data.target || this.data.type === 'map') { + var texture; + if (this.textureCache.has(this.data.src)) { + texture = this.textureCache.get(this.data.src); + } else { + texture = new THREE.TextureLoader().load(this.data.src); + this.textureCache.set(this.data.src, texture); + } + this.bboxMesh.material.map = texture; + this.bboxMesh.material.needsUpdate = true; + } + if (this.data.target && this.data.target.object3D) { + this.bbox.setFromObject(this.data.target.object3D); + this.bbox.getCenter(this.bboxMesh.position); + this.bbox.getSize(this.bboxMesh.scale); + if (this.data.type === 'footprint') { + // Add a little buffer for the footprint border + this.bboxMesh.scale.x *= 1.04; + this.bboxMesh.scale.z *= 1.04; + this.updateFootprint(); + } + this.bboxMesh.position.y -= this.bboxMesh.scale.y / 2; + this.bboxOffset.copy(this.bboxMesh.position); + this.bboxOffset.sub(this.data.target.object3D.position); + } else { + this.bboxMesh.scale.set(this.data.mapSize.x, 1, this.data.mapSize.y); + } + } + if (this.hitTest) { + pose = this.hitTest.doHit(frame); + if (pose) { + if (this.hasPosedOnce !== true) { + this.hasPosedOnce = true; + this.el.emit('ar-hit-test-achieved'); + } + this.bboxMesh.visible = true; + this.bboxMesh.position.copy(pose.transform.position); + this.bboxMesh.quaternion.copy(pose.transform.orientation); + } + } + } +}); + +/***/ }), + +/***/ "./src/components/scene/background.js": +/*!********************************************!*\ + !*** ./src/components/scene/background.js ***! + \********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/* global THREE */ +var register = (__webpack_require__(/*! ../../core/component */ "./src/core/component.js").registerComponent); +var COMPONENTS = (__webpack_require__(/*! ../../core/component */ "./src/core/component.js").components); +module.exports.Component = register('background', { + schema: { + color: { + type: 'color', + default: 'black' + }, + transparent: { + default: false + } + }, + update: function () { + var data = this.data; + var object3D = this.el.object3D; + if (data.transparent) { + object3D.background = null; + } else { + object3D.background = new THREE.Color(data.color); + } + }, + remove: function () { + var data = this.data; + var object3D = this.el.object3D; + if (data.transparent) { + object3D.background = null; + return; + } + object3D.background = COMPONENTS[this.name].schema.color.default; + } +}); + +/***/ }), + +/***/ "./src/components/scene/debug.js": +/*!***************************************!*\ + !*** ./src/components/scene/debug.js ***! + \***************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var register = (__webpack_require__(/*! ../../core/component */ "./src/core/component.js").registerComponent); +module.exports.Component = register('debug', { + schema: { + default: true + } +}); + +/***/ }), + +/***/ "./src/components/scene/device-orientation-permission-ui.js": +/*!******************************************************************!*\ + !*** ./src/components/scene/device-orientation-permission-ui.js ***! + \******************************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/* global DeviceOrientationEvent, location */ +var registerComponent = (__webpack_require__(/*! ../../core/component */ "./src/core/component.js").registerComponent); +var utils = __webpack_require__(/*! ../../utils/ */ "./src/utils/index.js"); +var bind = utils.bind; +var constants = __webpack_require__(/*! ../../constants/ */ "./src/constants/index.js"); +var MODAL_CLASS = 'a-modal'; +var DIALOG_CLASS = 'a-dialog'; +var DIALOG_TEXT_CLASS = 'a-dialog-text'; +var DIALOG_TEXT_CONTAINER_CLASS = 'a-dialog-text-container'; +var DIALOG_BUTTONS_CONTAINER_CLASS = 'a-dialog-buttons-container'; +var DIALOG_BUTTON_CLASS = 'a-dialog-button'; +var DIALOG_ALLOW_BUTTON_CLASS = 'a-dialog-allow-button'; +var DIALOG_DENY_BUTTON_CLASS = 'a-dialog-deny-button'; +var DIALOG_OK_BUTTON_CLASS = 'a-dialog-ok-button'; + +/** + * UI for enabling device motion permission + */ +module.exports.Component = registerComponent('device-orientation-permission-ui', { + schema: { + enabled: { + default: true + }, + deviceMotionMessage: { + default: 'This immersive website requires access to your device motion sensors.' + }, + httpsMessage: { + default: 'Access this site over HTTPS to enter VR mode and grant access to the device sensors.' + }, + denyButtonText: { + default: 'Deny' + }, + allowButtonText: { + default: 'Allow' + }, + cancelButtonText: { + default: 'Cancel' + } + }, + init: function () { + var self = this; + if (!this.data.enabled) { + return; + } + if (location.hostname !== 'localhost' && location.hostname !== '127.0.0.1' && location.protocol === 'http:') { + this.showHTTPAlert(); + } + + // Browser doesn't support or doesn't require permission to DeviceOrientationEvent API. + if (typeof DeviceOrientationEvent === 'undefined' || !DeviceOrientationEvent.requestPermission) { + this.permissionGranted = true; + return; + } + this.onDeviceMotionDialogAllowClicked = bind(this.onDeviceMotionDialogAllowClicked, this); + this.onDeviceMotionDialogDenyClicked = bind(this.onDeviceMotionDialogDenyClicked, this); + // Show dialog only if permission has not yet been granted. + DeviceOrientationEvent.requestPermission().then(function () { + self.el.emit('deviceorientationpermissiongranted'); + self.permissionGranted = true; + }).catch(function () { + self.devicePermissionDialogEl = createPermissionDialog(self.data.denyButtonText, self.data.allowButtonText, self.data.deviceMotionMessage, self.onDeviceMotionDialogAllowClicked, self.onDeviceMotionDialogDenyClicked); + self.el.appendChild(self.devicePermissionDialogEl); + }); + }, + remove: function () { + // This removes the modal screen + if (this.devicePermissionDialogEl) { + this.el.removeChild(this.devicePermissionDialogEl); + } + }, + onDeviceMotionDialogDenyClicked: function () { + this.remove(); + }, + showHTTPAlert: function () { + var self = this; + var httpAlertEl = createAlertDialog(self.data.cancelButtonText, self.data.httpsMessage, function () { + self.el.removeChild(httpAlertEl); + }); + this.el.appendChild(httpAlertEl); + }, + /** + * Enable device motion permission when clicked. + */ + onDeviceMotionDialogAllowClicked: function () { + var self = this; + this.el.emit('deviceorientationpermissionrequested'); + DeviceOrientationEvent.requestPermission().then(function (response) { + if (response === 'granted') { + self.el.emit('deviceorientationpermissiongranted'); + self.permissionGranted = true; + } else { + self.el.emit('deviceorientationpermissionrejected'); + } + self.remove(); + }).catch(console.error); + } +}); + +/** + * Create a modal dialog that request users permission to access the Device Motion API. + * + * @param {function} onAllowClicked - click event handler + * @param {function} onDenyClicked - click event handler + * + * @returns {Element} Wrapper
. + */ +function createPermissionDialog(denyText, allowText, dialogText, onAllowClicked, onDenyClicked) { + var buttonsContainer; + var denyButton; + var acceptButton; + buttonsContainer = document.createElement('div'); + buttonsContainer.classList.add(DIALOG_BUTTONS_CONTAINER_CLASS); + + // Buttons + denyButton = document.createElement('button'); + denyButton.classList.add(DIALOG_BUTTON_CLASS, DIALOG_DENY_BUTTON_CLASS); + denyButton.setAttribute(constants.AFRAME_INJECTED, ''); + denyButton.innerHTML = denyText; + buttonsContainer.appendChild(denyButton); + acceptButton = document.createElement('button'); + acceptButton.classList.add(DIALOG_BUTTON_CLASS, DIALOG_ALLOW_BUTTON_CLASS); + acceptButton.setAttribute(constants.AFRAME_INJECTED, ''); + acceptButton.innerHTML = allowText; + buttonsContainer.appendChild(acceptButton); + + // Ask for sensor events to be used + acceptButton.addEventListener('click', function (evt) { + evt.stopPropagation(); + onAllowClicked(); + }); + denyButton.addEventListener('click', function (evt) { + evt.stopPropagation(); + onDenyClicked(); + }); + return createDialog(dialogText, buttonsContainer); +} +function createAlertDialog(closeText, dialogText, onOkClicked) { + var buttonsContainer; + var okButton; + buttonsContainer = document.createElement('div'); + buttonsContainer.classList.add(DIALOG_BUTTONS_CONTAINER_CLASS); + + // Buttons + okButton = document.createElement('button'); + okButton.classList.add(DIALOG_BUTTON_CLASS, DIALOG_OK_BUTTON_CLASS); + okButton.setAttribute(constants.AFRAME_INJECTED, ''); + okButton.innerHTML = closeText; + buttonsContainer.appendChild(okButton); + + // Ask for sensor events to be used + okButton.addEventListener('click', function (evt) { + evt.stopPropagation(); + onOkClicked(); + }); + return createDialog(dialogText, buttonsContainer); +} +function createDialog(text, buttonsContainerEl) { + var modalContainer; + var dialog; + var dialogTextContainer; + var dialogText; + modalContainer = document.createElement('div'); + modalContainer.classList.add(MODAL_CLASS); + modalContainer.setAttribute(constants.AFRAME_INJECTED, ''); + dialog = document.createElement('div'); + dialog.className = DIALOG_CLASS; + dialog.setAttribute(constants.AFRAME_INJECTED, ''); + modalContainer.appendChild(dialog); + dialogTextContainer = document.createElement('div'); + dialogTextContainer.classList.add(DIALOG_TEXT_CONTAINER_CLASS); + dialog.appendChild(dialogTextContainer); + dialogText = document.createElement('div'); + dialogText.classList.add(DIALOG_TEXT_CLASS); + dialogText.innerHTML = text; + dialogTextContainer.appendChild(dialogText); + dialog.appendChild(buttonsContainerEl); + return modalContainer; +} + +/***/ }), + +/***/ "./src/components/scene/embedded.js": +/*!******************************************!*\ + !*** ./src/components/scene/embedded.js ***! + \******************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var registerComponent = (__webpack_require__(/*! ../../core/component */ "./src/core/component.js").registerComponent); + +/** + * Component to embed an a-frame scene within the layout of a 2D page. + */ +module.exports.Component = registerComponent('embedded', { + dependencies: ['vr-mode-ui'], + schema: { + default: true + }, + update: function () { + var sceneEl = this.el; + var enterVREl = sceneEl.querySelector('.a-enter-vr'); + if (this.data === true) { + if (enterVREl) { + enterVREl.classList.add('embedded'); + } + sceneEl.removeFullScreenStyles(); + } else { + if (enterVREl) { + enterVREl.classList.remove('embedded'); + } + sceneEl.addFullScreenStyles(); + } + } +}); + +/***/ }), + +/***/ "./src/components/scene/fog.js": +/*!*************************************!*\ + !*** ./src/components/scene/fog.js ***! + \*************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var register = (__webpack_require__(/*! ../../core/component */ "./src/core/component.js").registerComponent); +var THREE = __webpack_require__(/*! ../../lib/three */ "./src/lib/three.js"); +var debug = __webpack_require__(/*! ../../utils/debug */ "./src/utils/debug.js"); +var warn = debug('components:fog:warn'); + +/** + * Fog component. + * Applies only to the scene entity. + */ +module.exports.Component = register('fog', { + schema: { + color: { + type: 'color', + default: '#000' + }, + density: { + default: 0.00025 + }, + far: { + default: 1000, + min: 0 + }, + near: { + default: 1, + min: 0 + }, + type: { + default: 'linear', + oneOf: ['linear', 'exponential'] + } + }, + update: function () { + var data = this.data; + var el = this.el; + var fog = this.el.object3D.fog; + if (!el.isScene) { + warn('Fog component can only be applied to '); + return; + } + + // (Re)create fog if fog doesn't exist or fog type changed. + if (!fog || data.type !== fog.name) { + el.object3D.fog = getFog(data); + el.systems.material.updateMaterials(); + return; + } + + // Fog data changed. Update fog. + Object.keys(this.schema).forEach(function (key) { + var value = data[key]; + if (key === 'color') { + value = new THREE.Color(value); + } + fog[key] = value; + }); + }, + /** + * Remove fog on remove (callback). + */ + remove: function () { + var fog = this.el.object3D.fog; + if (!fog) { + return; + } + fog.far = 0; + fog.near = 0.1; + } +}); + +/** + * Creates a fog object. Sets fog.name to be able to detect fog type changes. + * + * @param {object} data - Fog data. + * @returns {object} fog + */ +function getFog(data) { + var fog; + if (data.type === 'exponential') { + fog = new THREE.FogExp2(data.color, data.density); + } else { + fog = new THREE.Fog(data.color, data.near, data.far); + } + fog.name = data.type; + return fog; +} + +/***/ }), + +/***/ "./src/components/scene/inspector.js": +/*!*******************************************!*\ + !*** ./src/components/scene/inspector.js ***! + \*******************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/* global AFRAME */ +var AFRAME_INJECTED = (__webpack_require__(/*! ../../constants */ "./src/constants/index.js").AFRAME_INJECTED); +var pkg = __webpack_require__(/*! ../../../package */ "./package.json"); +var registerComponent = (__webpack_require__(/*! ../../core/component */ "./src/core/component.js").registerComponent); +var utils = __webpack_require__(/*! ../../utils/ */ "./src/utils/index.js"); + +/** + * 0.4.2 to 0.4.x + * Will need to update this when A-Frame goes to 1.x.x. + */ +function getFuzzyPatchVersion(version) { + var split = version.split('.'); + split[2] = 'x'; + return split.join('.'); +} +var INSPECTOR_DEV_URL = 'https://aframe.io/aframe-inspector/dist/aframe-inspector.js'; +var INSPECTOR_RELEASE_URL = 'https://unpkg.com/aframe-inspector@' + getFuzzyPatchVersion(pkg.version) + '/dist/aframe-inspector.min.js'; +var INSPECTOR_URL = false ? 0 : INSPECTOR_RELEASE_URL; +var LOADING_MESSAGE = 'Loading Inspector'; +var LOADING_ERROR_MESSAGE = 'Error loading Inspector'; +module.exports.Component = registerComponent('inspector', { + schema: { + url: { + default: INSPECTOR_URL + } + }, + init: function () { + this.firstPlay = true; + this.onKeydown = this.onKeydown.bind(this); + this.onMessage = this.onMessage.bind(this); + this.initOverlay(); + window.addEventListener('keydown', this.onKeydown); + window.addEventListener('message', this.onMessage); + }, + play: function () { + var urlParam; + if (!this.firstPlay) { + return; + } + urlParam = utils.getUrlParameter('inspector'); + if (urlParam !== 'false' && !!urlParam) { + this.openInspector(); + this.firstPlay = false; + } + }, + initOverlay: function () { + var dotsHTML = '...'; + this.loadingMessageEl = document.createElement('div'); + this.loadingMessageEl.classList.add('a-inspector-loader'); + this.loadingMessageEl.innerHTML = LOADING_MESSAGE + dotsHTML; + }, + remove: function () { + this.removeEventListeners(); + }, + /** + * + + i keyboard shortcut. + */ + onKeydown: function (evt) { + var shortcutPressed = evt.keyCode === 73 && (evt.ctrlKey && evt.altKey || evt.getModifierState('AltGraph')); + if (!shortcutPressed) { + return; + } + this.openInspector(); + }, + showLoader: function () { + document.body.appendChild(this.loadingMessageEl); + }, + hideLoader: function () { + document.body.removeChild(this.loadingMessageEl); + }, + /** + * postMessage. aframe.io uses this to create a button on examples to open Inspector. + */ + onMessage: function (evt) { + if (evt.data === 'INJECT_AFRAME_INSPECTOR') { + this.openInspector(); + } + }, + openInspector: function (focusEl) { + var self = this; + var script; + + // Already injected. Open. + if (AFRAME.INSPECTOR || AFRAME.inspectorInjected) { + AFRAME.INSPECTOR.open(focusEl); + return; + } + this.showLoader(); + + // Inject. + script = document.createElement('script'); + script.src = this.data.url; + script.setAttribute('data-name', 'aframe-inspector'); + script.setAttribute(AFRAME_INJECTED, ''); + script.onload = function () { + AFRAME.INSPECTOR.open(focusEl); + self.hideLoader(); + self.removeEventListeners(); + }; + script.onerror = function () { + self.loadingMessageEl.innerHTML = LOADING_ERROR_MESSAGE; + }; + document.head.appendChild(script); + AFRAME.inspectorInjected = true; + }, + removeEventListeners: function () { + window.removeEventListener('keydown', this.onKeydown); + window.removeEventListener('message', this.onMessage); + } +}); + +/***/ }), + +/***/ "./src/components/scene/keyboard-shortcuts.js": +/*!****************************************************!*\ + !*** ./src/components/scene/keyboard-shortcuts.js ***! + \****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var registerComponent = (__webpack_require__(/*! ../../core/component */ "./src/core/component.js").registerComponent); +var shouldCaptureKeyEvent = (__webpack_require__(/*! ../../utils/ */ "./src/utils/index.js").shouldCaptureKeyEvent); +module.exports.Component = registerComponent('keyboard-shortcuts', { + schema: { + enterVR: { + default: true + }, + exitVR: { + default: true + } + }, + init: function () { + this.onKeyup = this.onKeyup.bind(this); + }, + update: function (oldData) { + var data = this.data; + this.enterVREnabled = data.enterVR; + }, + play: function () { + window.addEventListener('keyup', this.onKeyup, false); + }, + pause: function () { + window.removeEventListener('keyup', this.onKeyup); + }, + onKeyup: function (evt) { + var scene = this.el; + if (!shouldCaptureKeyEvent(evt)) { + return; + } + if (this.enterVREnabled && evt.keyCode === 70) { + // f. + scene.enterVR(); + } + if (this.enterVREnabled && evt.keyCode === 27) { + // escape. + scene.exitVR(); + } + } +}); + +/***/ }), + +/***/ "./src/components/scene/pool.js": +/*!**************************************!*\ + !*** ./src/components/scene/pool.js ***! + \**************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var debug = __webpack_require__(/*! ../../utils/debug */ "./src/utils/debug.js"); +var registerComponent = (__webpack_require__(/*! ../../core/component */ "./src/core/component.js").registerComponent); +var warn = debug('components:pool:warn'); + +/** + * Pool component to reuse entities. + * Avoids creating and destroying the same kind of entities. + * Helps reduce GC pauses. For example in a game to reuse enemies entities. + * + * @member {array} availableEls - Available entities in the pool. + * @member {array} usedEls - Entities of the pool in use. + */ +module.exports.Component = registerComponent('pool', { + schema: { + container: { + default: '' + }, + mixin: { + default: '' + }, + size: { + default: 0 + }, + dynamic: { + default: false + } + }, + multiple: true, + initPool: function () { + var i; + this.availableEls = []; + this.usedEls = []; + if (!this.data.mixin) { + warn('No mixin provided for pool component.'); + } + if (this.data.container) { + this.container = document.querySelector(this.data.container); + if (!this.container) { + warn('Container ' + this.data.container + ' not found.'); + } + } + this.container = this.container || this.el; + for (i = 0; i < this.data.size; ++i) { + this.createEntity(); + } + }, + update: function (oldData) { + var data = this.data; + if (oldData.mixin !== data.mixin || oldData.size !== data.size) { + this.initPool(); + } + }, + /** + * Add a new entity to the list of available entities. + */ + createEntity: function () { + var el; + el = document.createElement('a-entity'); + el.play = this.wrapPlay(el.play); + el.setAttribute('mixin', this.data.mixin); + el.object3D.visible = false; + el.pause(); + this.container.appendChild(el); + this.availableEls.push(el); + var usedEls = this.usedEls; + el.addEventListener('loaded', function () { + if (usedEls.indexOf(el) !== -1) { + return; + } + el.object3DParent = el.object3D.parent; + el.object3D.parent.remove(el.object3D); + }); + }, + /** + * Play wrapper for pooled entities. When pausing and playing a scene, don't want to play + * entities that are not in use. + */ + wrapPlay: function (playMethod) { + var usedEls = this.usedEls; + return function () { + if (usedEls.indexOf(this) === -1) { + return; + } + playMethod.call(this); + }; + }, + /** + * Used to request one of the available entities of the pool. + */ + requestEntity: function () { + var el; + if (this.availableEls.length === 0) { + if (this.data.dynamic === false) { + warn('Requested entity from empty pool: ' + this.attrName); + return; + } else { + warn('Requested entity from empty pool. This pool is dynamic and will resize ' + 'automatically. You might want to increase its initial size: ' + this.attrName); + } + this.createEntity(); + } + el = this.availableEls.shift(); + this.usedEls.push(el); + if (el.object3DParent) { + el.object3DParent.add(el.object3D); + this.updateRaycasters(); + } + el.object3D.visible = true; + return el; + }, + /** + * Used to return a used entity to the pool. + */ + returnEntity: function (el) { + var index = this.usedEls.indexOf(el); + if (index === -1) { + warn('The returned entity was not previously pooled from ' + this.attrName); + return; + } + this.usedEls.splice(index, 1); + this.availableEls.push(el); + el.object3DParent = el.object3D.parent; + el.object3D.parent.remove(el.object3D); + this.updateRaycasters(); + el.object3D.visible = false; + el.pause(); + return el; + }, + updateRaycasters() { + var raycasterEls = document.querySelectorAll('[raycaster]'); + raycasterEls.forEach(function (el) { + el.components['raycaster'].setDirty(); + }); + } +}); + +/***/ }), + +/***/ "./src/components/scene/reflection.js": +/*!********************************************!*\ + !*** ./src/components/scene/reflection.js ***! + \********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/* global THREE, XRWebGLBinding */ +var register = (__webpack_require__(/*! ../../core/component */ "./src/core/component.js").registerComponent); + +// source: view-source:https://storage.googleapis.com/chromium-webxr-test/r886480/proposals/lighting-estimation.html +function updateLights(estimate, probeLight, directionalLight, directionalLightPosition) { + var intensityScalar = Math.max(estimate.primaryLightIntensity.x, Math.max(estimate.primaryLightIntensity.y, estimate.primaryLightIntensity.z)); + probeLight.sh.fromArray(estimate.sphericalHarmonicsCoefficients); + probeLight.intensity = 1; + if (directionalLight) { + directionalLight.color.setRGB(estimate.primaryLightIntensity.x / intensityScalar, estimate.primaryLightIntensity.y / intensityScalar, estimate.primaryLightIntensity.z / intensityScalar); + directionalLight.intensity = intensityScalar; + directionalLightPosition.copy(estimate.primaryLightDirection); + } +} +module.exports.Component = register('reflection', { + schema: { + directionalLight: { + type: 'selector' + } + }, + init: function () { + var self = this; + this.cubeRenderTarget = new THREE.WebGLCubeRenderTarget(16); + this.cubeCamera = new THREE.CubeCamera(0.1, 1000, this.cubeRenderTarget); + this.lightingEstimationTexture = new THREE.WebGLCubeRenderTarget(16).texture; + this.needsVREnvironmentUpdate = true; + + // Update WebXR to support light-estimation + var webxrData = this.el.getAttribute('webxr'); + var optionalFeaturesArray = webxrData.optionalFeatures; + if (!optionalFeaturesArray.includes('light-estimation')) { + optionalFeaturesArray.push('light-estimation'); + this.el.setAttribute('webxr', webxrData); + } + this.el.addEventListener('enter-vr', function () { + var renderer = self.el.renderer; + var session = renderer.xr.getSession(); + if (session.requestLightProbe && self.el.is('ar-mode')) { + self.startLightProbe(); + } + }); + this.el.addEventListener('exit-vr', function () { + self.stopLightProbe(); + }); + this.el.object3D.environment = this.cubeRenderTarget.texture; + }, + stopLightProbe: function () { + this.xrLightProbe = null; + if (this.probeLight) { + this.probeLight.components.light.light.intensity = 0; + } + this.needsVREnvironmentUpdate = true; + this.el.object3D.environment = this.cubeRenderTarget.texture; + }, + startLightProbe: function () { + this.needsLightProbeUpdate = true; + }, + setupLightProbe: function () { + var renderer = this.el.renderer; + var xrSession = renderer.xr.getSession(); + var self = this; + var gl = renderer.getContext(); + if (!this.probeLight) { + var probeLight = document.createElement('a-light'); + probeLight.setAttribute('type', 'probe'); + probeLight.setAttribute('intensity', 0); + this.el.appendChild(probeLight); + this.probeLight = probeLight; + } + + // Ensure that we have any extensions needed to use the preferred cube map format. + switch (xrSession.preferredReflectionFormat) { + case 'srgba8': + gl.getExtension('EXT_sRGB'); + break; + case 'rgba16f': + gl.getExtension('OES_texture_half_float'); + break; + } + this.glBinding = new XRWebGLBinding(xrSession, gl); + gl.getExtension('EXT_sRGB'); + gl.getExtension('OES_texture_half_float'); + xrSession.requestLightProbe().then(function (lightProbe) { + self.xrLightProbe = lightProbe; + lightProbe.addEventListener('reflectionchange', self.updateXRCubeMap.bind(self)); + }).catch(function (err) { + console.warn('Lighting estimation not supported: ' + err.message); + console.warn('Are you missing: webxr="optionalFeatures: light-estimation;" from ?'); + }); + }, + updateXRCubeMap: function () { + // Update Cube Map, cubeMap maybe some unavailable on some hardware + var renderer = this.el.renderer; + var cubeMap = this.glBinding.getReflectionCubeMap(this.xrLightProbe); + if (cubeMap) { + var rendererProps = renderer.properties.get(this.lightingEstimationTexture); + rendererProps.__webglTexture = cubeMap; + this.lightingEstimationTexture.needsPMREMUpdate = true; + this.el.object3D.environment = this.lightingEstimationTexture; + } + }, + tick: function () { + var scene = this.el.object3D; + var renderer = this.el.renderer; + var frame = this.el.frame; + if (frame && this.xrLightProbe) { + // light estimate may not yet be available, it takes a few frames to start working + var estimate = frame.getLightEstimate(this.xrLightProbe); + if (estimate) { + updateLights(estimate, this.probeLight.components.light.light, this.data.directionalLight && this.data.directionalLight.components.light.light, this.data.directionalLight && this.data.directionalLight.object3D.position); + } + } + if (this.needsVREnvironmentUpdate) { + scene.environment = null; + this.needsVREnvironmentUpdate = false; + this.cubeCamera.position.set(0, 1.6, 0); + this.cubeCamera.update(renderer, scene); + scene.environment = this.cubeRenderTarget.texture; + } + if (this.needsLightProbeUpdate && frame) { + // wait until the XR Session has started before trying to make + // the light probe + this.setupLightProbe(); + this.needsLightProbeUpdate = false; + } + }, + remove: function () { + this.el.object3D.environment = null; + if (this.probeLight) { + this.el.removeChild(this.probeLight); + } + } +}); + +/***/ }), + +/***/ "./src/components/scene/screenshot.js": +/*!********************************************!*\ + !*** ./src/components/scene/screenshot.js ***! + \********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/* global ImageData, URL */ +var registerComponent = (__webpack_require__(/*! ../../core/component */ "./src/core/component.js").registerComponent); +var THREE = __webpack_require__(/*! ../../lib/three */ "./src/lib/three.js"); +var VERTEX_SHADER = ['attribute vec3 position;', 'attribute vec2 uv;', 'uniform mat4 projectionMatrix;', 'uniform mat4 modelViewMatrix;', 'varying vec2 vUv;', 'void main() {', ' vUv = vec2( 1.- uv.x, uv.y );', ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', '}'].join('\n'); +var FRAGMENT_SHADER = ['precision mediump float;', 'uniform samplerCube map;', 'varying vec2 vUv;', '#define M_PI 3.141592653589793238462643383279', 'void main() {', ' vec2 uv = vUv;', ' float longitude = uv.x * 2. * M_PI - M_PI + M_PI / 2.;', ' float latitude = uv.y * M_PI;', ' vec3 dir = vec3(', ' - sin( longitude ) * sin( latitude ),', ' cos( latitude ),', ' - cos( longitude ) * sin( latitude )', ' );', ' normalize( dir );', ' gl_FragColor = vec4( textureCube( map, dir ).rgb, 1.0 );', '}'].join('\n'); + +/** + * Component to take screenshots of the scene using a keboard shortcut (alt+s). + * It can be configured to either take 360° captures (`equirectangular`) + * or regular screenshots (`projection`) + * + * This is based on https://github.com/spite/THREE.CubemapToEquirectangular + * To capture an equirectangular projection of the scene a THREE.CubeCamera is used + * The cube map produced by the CubeCamera is projected on a quad and then rendered to + * WebGLRenderTarget with an ortographic camera. + */ +module.exports.Component = registerComponent('screenshot', { + schema: { + width: { + default: 4096 + }, + height: { + default: 2048 + }, + camera: { + type: 'selector' + } + }, + init: function () { + var el = this.el; + var self = this; + if (el.renderer) { + setup(); + } else { + el.addEventListener('render-target-loaded', setup); + } + function setup() { + var gl = el.renderer.getContext(); + if (!gl) { + return; + } + self.cubeMapSize = gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE); + self.material = new THREE.RawShaderMaterial({ + uniforms: { + map: { + type: 't', + value: null + } + }, + vertexShader: VERTEX_SHADER, + fragmentShader: FRAGMENT_SHADER, + side: THREE.DoubleSide + }); + self.quad = new THREE.Mesh(new THREE.PlaneGeometry(1, 1), self.material); + self.quad.visible = false; + self.camera = new THREE.OrthographicCamera(-1 / 2, 1 / 2, 1 / 2, -1 / 2, -10000, 10000); + self.canvas = document.createElement('canvas'); + self.ctx = self.canvas.getContext('2d'); + el.object3D.add(self.quad); + self.onKeyDown = self.onKeyDown.bind(self); + } + }, + getRenderTarget: function (width, height) { + return new THREE.WebGLRenderTarget(width, height, { + encoding: this.el.sceneEl.renderer.outputEncoding, + minFilter: THREE.LinearFilter, + magFilter: THREE.LinearFilter, + wrapS: THREE.ClampToEdgeWrapping, + wrapT: THREE.ClampToEdgeWrapping, + format: THREE.RGBAFormat, + type: THREE.UnsignedByteType + }); + }, + resize: function (width, height) { + // Resize quad. + this.quad.scale.set(width, height, 1); + + // Resize camera. + this.camera.left = -1 * width / 2; + this.camera.right = width / 2; + this.camera.top = height / 2; + this.camera.bottom = -1 * height / 2; + this.camera.updateProjectionMatrix(); + + // Resize canvas. + this.canvas.width = width; + this.canvas.height = height; + }, + play: function () { + window.addEventListener('keydown', this.onKeyDown); + }, + /** + * + + s = Regular screenshot. + * + + + s = Equirectangular screenshot. + */ + onKeyDown: function (evt) { + var shortcutPressed = evt.keyCode === 83 && evt.ctrlKey && evt.altKey; + if (!this.data || !shortcutPressed) { + return; + } + var projection = evt.shiftKey ? 'equirectangular' : 'perspective'; + this.capture(projection); + }, + /** + * Capture a screenshot of the scene. + * + * @param {string} projection - Screenshot projection (equirectangular or perspective). + */ + setCapture: function (projection) { + var el = this.el; + var size; + var camera; + var cubeCamera; + var cubeRenderTarget; + // Configure camera. + if (projection === 'perspective') { + // Quad is only used in equirectangular mode. Hide it in this case. + this.quad.visible = false; + // Use scene camera. + camera = this.data.camera && this.data.camera.components.camera.camera || el.camera; + size = { + width: this.data.width, + height: this.data.height + }; + } else { + // Use ortho camera. + camera = this.camera; + cubeRenderTarget = new THREE.WebGLCubeRenderTarget(Math.min(this.cubeMapSize, 2048), { + format: THREE.RGBFormat, + generateMipmaps: true, + minFilter: THREE.LinearMipmapLinearFilter, + encoding: THREE.sRGBEncoding + }); + // Create cube camera and copy position from scene camera. + cubeCamera = new THREE.CubeCamera(el.camera.near, el.camera.far, cubeRenderTarget); + // Copy camera position into cube camera; + el.camera.getWorldPosition(cubeCamera.position); + el.camera.getWorldQuaternion(cubeCamera.quaternion); + // Render scene with cube camera. + cubeCamera.update(el.renderer, el.object3D); + this.quad.material.uniforms.map.value = cubeCamera.renderTarget.texture; + size = { + width: this.data.width, + height: this.data.height + }; + // Use quad to project image taken by the cube camera. + this.quad.visible = true; + } + return { + camera: camera, + size: size, + projection: projection + }; + }, + /** + * Maintained for backwards compatibility. + */ + capture: function (projection) { + var isVREnabled = this.el.renderer.xr.enabled; + var renderer = this.el.renderer; + var params; + // Disable VR. + renderer.xr.enabled = false; + params = this.setCapture(projection); + this.renderCapture(params.camera, params.size, params.projection); + // Trigger file download. + this.saveCapture(); + // Restore VR. + renderer.xr.enabled = isVREnabled; + }, + /** + * Return canvas instead of triggering download (e.g., for uploading blob to server). + */ + getCanvas: function (projection) { + var isVREnabled = this.el.renderer.xr.enabled; + var renderer = this.el.renderer; + // Disable VR. + var params = this.setCapture(projection); + renderer.xr.enabled = false; + this.renderCapture(params.camera, params.size, params.projection); + // Restore VR. + renderer.xr.enabled = isVREnabled; + return this.canvas; + }, + renderCapture: function (camera, size, projection) { + var autoClear = this.el.renderer.autoClear; + var el = this.el; + var imageData; + var output; + var pixels; + var renderer = el.renderer; + // Create rendering target and buffer to store the read pixels. + output = this.getRenderTarget(size.width, size.height); + pixels = new Uint8Array(4 * size.width * size.height); + // Resize quad, camera, and canvas. + this.resize(size.width, size.height); + // Render scene to render target. + renderer.autoClear = true; + renderer.clear(); + renderer.setRenderTarget(output); + renderer.render(el.object3D, camera); + renderer.autoClear = autoClear; + // Read image pizels back. + renderer.readRenderTargetPixels(output, 0, 0, size.width, size.height, pixels); + renderer.setRenderTarget(null); + if (projection === 'perspective') { + pixels = this.flipPixelsVertically(pixels, size.width, size.height); + } + imageData = new ImageData(new Uint8ClampedArray(pixels), size.width, size.height); + // Hide quad after projecting the image. + this.quad.visible = false; + // Copy pixels into canvas. + this.ctx.putImageData(imageData, 0, 0); + }, + flipPixelsVertically: function (pixels, width, height) { + var flippedPixels = pixels.slice(0); + for (var x = 0; x < width; ++x) { + for (var y = 0; y < height; ++y) { + flippedPixels[x * 4 + y * width * 4] = pixels[x * 4 + (height - y) * width * 4]; + flippedPixels[x * 4 + 1 + y * width * 4] = pixels[x * 4 + 1 + (height - y) * width * 4]; + flippedPixels[x * 4 + 2 + y * width * 4] = pixels[x * 4 + 2 + (height - y) * width * 4]; + flippedPixels[x * 4 + 3 + y * width * 4] = pixels[x * 4 + 3 + (height - y) * width * 4]; + } + } + return flippedPixels; + }, + /** + * Download capture to file. + */ + saveCapture: function () { + this.canvas.toBlob(function (blob) { + var fileName = 'screenshot-' + document.title.toLowerCase() + '-' + Date.now() + '.png'; + var linkEl = document.createElement('a'); + var url = URL.createObjectURL(blob); + linkEl.href = url; + linkEl.setAttribute('download', fileName); + linkEl.innerHTML = 'downloading...'; + linkEl.style.display = 'none'; + document.body.appendChild(linkEl); + setTimeout(function () { + linkEl.click(); + document.body.removeChild(linkEl); + }, 1); + }, 'image/png'); + } +}); + +/***/ }), + +/***/ "./src/components/scene/stats.js": +/*!***************************************!*\ + !*** ./src/components/scene/stats.js ***! + \***************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var registerComponent = (__webpack_require__(/*! ../../core/component */ "./src/core/component.js").registerComponent); +var RStats = __webpack_require__(/*! ../../../vendor/rStats */ "./vendor/rStats.js"); +var utils = __webpack_require__(/*! ../../utils */ "./src/utils/index.js"); +__webpack_require__(/*! ../../../vendor/rStats.extras */ "./vendor/rStats.extras.js"); +__webpack_require__(/*! ../../lib/rStatsAframe */ "./src/lib/rStatsAframe.js"); +var AFrameStats = window.aframeStats; +var bind = utils.bind; +var HIDDEN_CLASS = 'a-hidden'; +var ThreeStats = window.threeStats; + +/** + * Stats appended to document.body by RStats. + */ +module.exports.Component = registerComponent('stats', { + schema: { + default: true + }, + init: function () { + var scene = this.el; + if (utils.getUrlParameter('stats') === 'false') { + return; + } + this.stats = createStats(scene); + this.statsEl = document.querySelector('.rs-base'); + this.hideBound = bind(this.hide, this); + this.showBound = bind(this.show, this); + scene.addEventListener('enter-vr', this.hideBound); + scene.addEventListener('exit-vr', this.showBound); + }, + update: function () { + if (!this.stats) { + return; + } + return !this.data ? this.hide() : this.show(); + }, + remove: function () { + this.el.removeEventListener('enter-vr', this.hideBound); + this.el.removeEventListener('exit-vr', this.showBound); + if (!this.statsEl) { + return; + } // Scene detached. + this.statsEl.parentNode.removeChild(this.statsEl); + }, + tick: function () { + var stats = this.stats; + if (!stats) { + return; + } + stats('rAF').tick(); + stats('FPS').frame(); + stats().update(); + }, + hide: function () { + this.statsEl.classList.add(HIDDEN_CLASS); + }, + show: function () { + this.statsEl.classList.remove(HIDDEN_CLASS); + } +}); +function createStats(scene) { + var threeStats = new ThreeStats(scene.renderer); + var aframeStats = new AFrameStats(scene); + var plugins = scene.isMobile ? [] : [threeStats, aframeStats]; + return new RStats({ + css: [], + // Our stylesheet is injected from `src/index.js`. + values: { + fps: { + caption: 'fps', + below: 30 + } + }, + groups: [{ + caption: 'Framerate', + values: ['fps', 'raf'] + }], + plugins: plugins + }); +} + +/***/ }), + +/***/ "./src/components/scene/vr-mode-ui.js": +/*!********************************************!*\ + !*** ./src/components/scene/vr-mode-ui.js ***! + \********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var registerComponent = (__webpack_require__(/*! ../../core/component */ "./src/core/component.js").registerComponent); +var constants = __webpack_require__(/*! ../../constants/ */ "./src/constants/index.js"); +var utils = __webpack_require__(/*! ../../utils/ */ "./src/utils/index.js"); +var bind = utils.bind; +var ENTER_VR_CLASS = 'a-enter-vr'; +var ENTER_AR_CLASS = 'a-enter-ar'; +var ENTER_VR_BTN_CLASS = 'a-enter-vr-button'; +var ENTER_AR_BTN_CLASS = 'a-enter-ar-button'; +var HIDDEN_CLASS = 'a-hidden'; +var ORIENTATION_MODAL_CLASS = 'a-orientation-modal'; + +/** + * UI for entering VR mode. + */ +module.exports.Component = registerComponent('vr-mode-ui', { + dependencies: ['canvas'], + schema: { + enabled: { + default: true + }, + cardboardModeEnabled: { + default: false + }, + enterVRButton: { + default: '' + }, + enterARButton: { + default: '' + } + }, + init: function () { + var self = this; + var sceneEl = this.el; + if (utils.getUrlParameter('ui') === 'false') { + return; + } + this.insideLoader = false; + this.enterVREl = null; + this.enterAREl = null; + this.orientationModalEl = null; + this.bindMethods(); + + // Hide/show VR UI when entering/exiting VR mode. + sceneEl.addEventListener('enter-vr', this.updateEnterInterfaces); + sceneEl.addEventListener('exit-vr', this.updateEnterInterfaces); + sceneEl.addEventListener('update-vr-devices', this.updateEnterInterfaces); + window.addEventListener('message', function (event) { + if (event.data.type === 'loaderReady') { + self.insideLoader = true; + self.remove(); + } + }); + + // Modal that tells the user to change orientation if in portrait. + window.addEventListener('orientationchange', this.toggleOrientationModalIfNeeded); + }, + bindMethods: function () { + this.onEnterVRButtonClick = bind(this.onEnterVRButtonClick, this); + this.onEnterARButtonClick = bind(this.onEnterARButtonClick, this); + this.onModalClick = bind(this.onModalClick, this); + this.toggleOrientationModalIfNeeded = bind(this.toggleOrientationModalIfNeeded, this); + this.updateEnterInterfaces = bind(this.updateEnterInterfaces, this); + }, + /** + * Exit VR when modal clicked. + */ + onModalClick: function () { + this.el.exitVR(); + }, + /** + * Enter VR when clicked. + */ + onEnterVRButtonClick: function () { + this.el.enterVR(); + }, + /** + * Enter AR when clicked. + */ + onEnterARButtonClick: function () { + this.el.enterAR(); + }, + update: function () { + var data = this.data; + var sceneEl = this.el; + if (!data.enabled || this.insideLoader || utils.getUrlParameter('ui') === 'false') { + return this.remove(); + } + if (this.enterVREl || this.enterAREl || this.orientationModalEl) { + return; + } + + // Add UI if enabled and not already present. + if (data.enterVRButton) { + // Custom button. + this.enterVREl = document.querySelector(data.enterVRButton); + this.enterVREl.addEventListener('click', this.onEnterVRButtonClick); + } else { + this.enterVREl = createEnterVRButton(this.onEnterVRButtonClick); + sceneEl.appendChild(this.enterVREl); + } + if (data.enterARButton) { + // Custom button. + this.enterAREl = document.querySelector(data.enterARButton); + this.enterAREl.addEventListener('click', this.onEnterARButtonClick); + } else { + this.enterAREl = createEnterARButton(this.onEnterARButtonClick); + sceneEl.appendChild(this.enterAREl); + } + this.orientationModalEl = createOrientationModal(this.onModalClick); + sceneEl.appendChild(this.orientationModalEl); + this.updateEnterInterfaces(); + }, + remove: function () { + [this.enterVREl, this.enterAREl, this.orientationModalEl].forEach(function (uiElement) { + if (uiElement && uiElement.parentNode) { + uiElement.parentNode.removeChild(uiElement); + } + }); + this.enterVREl = undefined; + this.enterAREl = undefined; + this.orientationModalEl = undefined; + }, + updateEnterInterfaces: function () { + this.toggleEnterVRButtonIfNeeded(); + this.toggleEnterARButtonIfNeeded(); + this.toggleOrientationModalIfNeeded(); + }, + toggleEnterVRButtonIfNeeded: function () { + var sceneEl = this.el; + if (!this.enterVREl) { + return; + } + if (sceneEl.is('vr-mode') || (sceneEl.isMobile || utils.device.isMobileDeviceRequestingDesktopSite()) && !this.data.cardboardModeEnabled && !utils.device.checkVRSupport()) { + this.enterVREl.classList.add(HIDDEN_CLASS); + } else { + if (!utils.device.checkVRSupport()) { + this.enterVREl.classList.add('fullscreen'); + } + this.enterVREl.classList.remove(HIDDEN_CLASS); + } + }, + toggleEnterARButtonIfNeeded: function () { + var sceneEl = this.el; + if (!this.enterAREl) { + return; + } + // Hide the button while in a session, or if AR is not supported. + if (sceneEl.is('vr-mode') || !utils.device.checkARSupport()) { + this.enterAREl.classList.add(HIDDEN_CLASS); + } else { + this.enterAREl.classList.remove(HIDDEN_CLASS); + } + }, + toggleOrientationModalIfNeeded: function () { + var sceneEl = this.el; + var orientationModalEl = this.orientationModalEl; + if (!orientationModalEl || !sceneEl.isMobile) { + return; + } + if (!utils.device.isLandscape() && sceneEl.is('vr-mode')) { + // Show if in VR mode on portrait. + orientationModalEl.classList.remove(HIDDEN_CLASS); + } else { + orientationModalEl.classList.add(HIDDEN_CLASS); + } + } +}); + +/** + * Create a button that when clicked will enter into stereo-rendering mode for VR. + * + * Structure:
+ * + * @param {function} onClick - click event handler + * @returns {Element} Wrapper
. + */ +function createEnterVRButton(onClick) { + var vrButton; + var wrapper; + + // Create elements. + wrapper = document.createElement('div'); + wrapper.classList.add(ENTER_VR_CLASS); + wrapper.setAttribute(constants.AFRAME_INJECTED, ''); + vrButton = document.createElement('button'); + vrButton.className = ENTER_VR_BTN_CLASS; + vrButton.setAttribute('title', 'Enter VR mode with a headset or fullscreen without'); + vrButton.setAttribute(constants.AFRAME_INJECTED, ''); + if (utils.device.isMobile()) { + applyStickyHoverFix(vrButton); + } + // Insert elements. + wrapper.appendChild(vrButton); + vrButton.addEventListener('click', function (evt) { + onClick(); + evt.stopPropagation(); + }); + return wrapper; +} + +/** + * Create a button that when clicked will enter into AR mode + * + * Structure:
+ * + * @param {function} onClick - click event handler + * @returns {Element} Wrapper
. + */ +function createEnterARButton(onClick) { + var arButton; + var wrapper; + + // Create elements. + wrapper = document.createElement('div'); + wrapper.classList.add(ENTER_AR_CLASS); + wrapper.setAttribute(constants.AFRAME_INJECTED, ''); + arButton = document.createElement('button'); + arButton.className = ENTER_AR_BTN_CLASS; + arButton.setAttribute('title', 'Enter AR mode with a headset or handheld device.'); + arButton.setAttribute(constants.AFRAME_INJECTED, ''); + if (utils.device.isMobile()) { + applyStickyHoverFix(arButton); + } + // Insert elements. + wrapper.appendChild(arButton); + arButton.addEventListener('click', function (evt) { + onClick(); + evt.stopPropagation(); + }); + return wrapper; +} + +/** + * Creates a modal dialog to request the user to switch to landscape orientation. + * + * @param {function} onClick - click event handler + * @returns {Element} Wrapper
. + */ +function createOrientationModal(onClick) { + var modal = document.createElement('div'); + modal.className = ORIENTATION_MODAL_CLASS; + modal.classList.add(HIDDEN_CLASS); + modal.setAttribute(constants.AFRAME_INJECTED, ''); + var exit = document.createElement('button'); + exit.setAttribute(constants.AFRAME_INJECTED, ''); + exit.innerHTML = 'Exit VR'; + + // Exit VR on close. + exit.addEventListener('click', onClick); + modal.appendChild(exit); + return modal; +} + +/** + * CSS hover state is sticky in iOS (as in 12/18/2019) + * They are not removed on mouseleave and this function applies a class + * to resets the style. + * + * @param {function} buttonEl - Button element + */ +function applyStickyHoverFix(buttonEl) { + buttonEl.addEventListener('touchstart', function () { + buttonEl.classList.remove('resethover'); + }); + buttonEl.addEventListener('touchend', function () { + buttonEl.classList.add('resethover'); + }); +} + +/***/ }), + +/***/ "./src/components/shadow.js": +/*!**********************************!*\ + !*** ./src/components/shadow.js ***! + \**********************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var component = __webpack_require__(/*! ../core/component */ "./src/core/component.js"); +var THREE = __webpack_require__(/*! ../lib/three */ "./src/lib/three.js"); +var bind = __webpack_require__(/*! ../utils/bind */ "./src/utils/bind.js"); +var registerComponent = component.registerComponent; + +/** + * Shadow component. + * + * When applied to an entity, that entity's geometry and any descendants will cast or receive + * shadows as specified by the `cast` and `receive` properties. + */ +module.exports.Component = registerComponent('shadow', { + schema: { + cast: { + default: true + }, + receive: { + default: true + } + }, + init: function () { + this.onMeshChanged = bind(this.update, this); + this.el.addEventListener('object3dset', this.onMeshChanged); + this.system.setShadowMapEnabled(true); + }, + update: function () { + var data = this.data; + this.updateDescendants(data.cast, data.receive); + }, + remove: function () { + var el = this.el; + el.removeEventListener('object3dset', this.onMeshChanged); + this.updateDescendants(false, false); + }, + updateDescendants: function (cast, receive) { + var sceneEl = this.el.sceneEl; + this.el.object3D.traverse(function (node) { + if (!(node instanceof THREE.Mesh)) { + return; + } + node.castShadow = cast; + node.receiveShadow = receive; + + // If scene has already rendered, materials must be updated. + if (sceneEl.hasLoaded && node.material) { + var materials = Array.isArray(node.material) ? node.material : [node.material]; + for (var i = 0; i < materials.length; i++) { + materials[i].needsUpdate = true; + } + } + }); + } +}); + +/***/ }), + +/***/ "./src/components/sound.js": +/*!*********************************!*\ + !*** ./src/components/sound.js ***! + \*********************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var debug = __webpack_require__(/*! ../utils/debug */ "./src/utils/debug.js"); +var THREE = __webpack_require__(/*! ../lib/three */ "./src/lib/three.js"); +var warn = debug('components:sound:warn'); + +/** + * Sound component. + */ +module.exports.Component = registerComponent('sound', { + schema: { + autoplay: { + default: false + }, + distanceModel: { + default: 'inverse', + oneOf: ['linear', 'inverse', 'exponential'] + }, + loop: { + default: false + }, + maxDistance: { + default: 10000 + }, + on: { + default: '' + }, + poolSize: { + default: 1 + }, + positional: { + default: true + }, + refDistance: { + default: 1 + }, + rolloffFactor: { + default: 1 + }, + src: { + type: 'audio' + }, + volume: { + default: 1 + } + }, + multiple: true, + init: function () { + var self = this; + this.listener = null; + this.audioLoader = new THREE.AudioLoader(); + this.pool = new THREE.Group(); + this.loaded = false; + this.mustPlay = false; + + // Don't pass evt because playSound takes a function as parameter. + this.playSoundBound = function () { + self.playSound(); + }; + }, + update: function (oldData) { + var data = this.data; + var i; + var sound; + var srcChanged = data.src !== oldData.src; + + // Create new sound if not yet created or changing `src`. + if (srcChanged) { + if (!data.src) { + return; + } + this.setupSound(); + } + for (i = 0; i < this.pool.children.length; i++) { + sound = this.pool.children[i]; + if (data.positional) { + sound.setDistanceModel(data.distanceModel); + sound.setMaxDistance(data.maxDistance); + sound.setRefDistance(data.refDistance); + sound.setRolloffFactor(data.rolloffFactor); + } + sound.setLoop(data.loop); + sound.setVolume(data.volume); + sound.isPaused = false; + } + if (data.on !== oldData.on) { + this.updateEventListener(oldData.on); + } + + // All sound values set. Load in `src`. + if (srcChanged) { + var self = this; + this.loaded = false; + this.audioLoader.load(data.src, function (buffer) { + for (i = 0; i < self.pool.children.length; i++) { + sound = self.pool.children[i]; + sound.setBuffer(buffer); + } + self.loaded = true; + + // Remove this key from cache, otherwise we can't play it again + THREE.Cache.remove(data.src); + if (self.data.autoplay || self.mustPlay) { + self.playSound(); + } + self.el.emit('sound-loaded', self.evtDetail, false); + }); + } + }, + pause: function () { + this.stopSound(); + this.removeEventListener(); + }, + play: function () { + if (this.data.autoplay) { + this.playSound(); + } + this.updateEventListener(); + }, + remove: function () { + var i; + var sound; + this.removeEventListener(); + if (this.el.getObject3D(this.attrName)) { + this.el.removeObject3D(this.attrName); + } + try { + for (i = 0; i < this.pool.children.length; i++) { + sound = this.pool.children[i]; + sound.disconnect(); + } + } catch (e) { + // disconnect() will throw if it was never connected initially. + warn('Audio source not properly disconnected'); + } + }, + /** + * Update listener attached to the user defined on event. + */ + updateEventListener: function (oldEvt) { + var el = this.el; + if (oldEvt) { + el.removeEventListener(oldEvt, this.playSoundBound); + } + el.addEventListener(this.data.on, this.playSoundBound); + }, + removeEventListener: function () { + this.el.removeEventListener(this.data.on, this.playSoundBound); + }, + /** + * Removes current sound object, creates new sound object, adds to entity. + * + * @returns {object} sound + */ + setupSound: function () { + var el = this.el; + var i; + var sceneEl = el.sceneEl; + var self = this; + var sound; + if (this.pool.children.length > 0) { + this.stopSound(); + el.removeObject3D('sound'); + } + + // Only want one AudioListener. Cache it on the scene. + var listener = this.listener = sceneEl.audioListener || new THREE.AudioListener(); + sceneEl.audioListener = listener; + if (sceneEl.camera) { + sceneEl.camera.add(listener); + } + + // Wait for camera if necessary. + sceneEl.addEventListener('camera-set-active', function (evt) { + evt.detail.cameraEl.getObject3D('camera').add(listener); + }); + + // Create [poolSize] audio instances and attach them to pool + this.pool = new THREE.Group(); + for (i = 0; i < this.data.poolSize; i++) { + sound = this.data.positional ? new THREE.PositionalAudio(listener) : new THREE.Audio(listener); + this.pool.add(sound); + } + el.setObject3D(this.attrName, this.pool); + for (i = 0; i < this.pool.children.length; i++) { + sound = this.pool.children[i]; + sound.onEnded = function () { + this.isPlaying = false; + self.el.emit('sound-ended', self.evtDetail, false); + }; + } + }, + /** + * Pause all the sounds in the pool. + */ + pauseSound: function () { + var i; + var sound; + this.isPlaying = false; + for (i = 0; i < this.pool.children.length; i++) { + sound = this.pool.children[i]; + if (!sound.source || !sound.source.buffer || !sound.isPlaying || sound.isPaused) { + continue; + } + sound.isPaused = true; + sound.pause(); + } + }, + /** + * Look for an unused sound in the pool and play it if found. + */ + playSound: function (processSound) { + var found; + var i; + var sound; + if (!this.loaded) { + warn('Sound not loaded yet. It will be played once it finished loading'); + this.mustPlay = true; + return; + } + found = false; + this.isPlaying = true; + for (i = 0; i < this.pool.children.length; i++) { + sound = this.pool.children[i]; + if (!sound.isPlaying && sound.buffer && !found) { + if (processSound) { + processSound(sound); + } + sound.play(); + sound.isPaused = false; + found = true; + continue; + } + } + if (!found) { + warn('All the sounds are playing. If you need to play more sounds simultaneously ' + 'consider increasing the size of pool with the `poolSize` attribute.', this.el); + return; + } + this.mustPlay = false; + }, + /** + * Stop all the sounds in the pool. + */ + stopSound: function () { + var i; + var sound; + this.isPlaying = false; + for (i = 0; i < this.pool.children.length; i++) { + sound = this.pool.children[i]; + if (!sound.source || !sound.source.buffer) { + return; + } + sound.stop(); + } + } +}); + +/***/ }), + +/***/ "./src/components/text.js": +/*!********************************!*\ + !*** ./src/components/text.js ***! + \********************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var createTextGeometry = __webpack_require__(/*! three-bmfont-text */ "./node_modules/three-bmfont-text/index.js"); +var loadBMFont = __webpack_require__(/*! load-bmfont */ "./node_modules/load-bmfont/browser.js"); +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var coreShader = __webpack_require__(/*! ../core/shader */ "./src/core/shader.js"); +var THREE = __webpack_require__(/*! ../lib/three */ "./src/lib/three.js"); +var utils = __webpack_require__(/*! ../utils/ */ "./src/utils/index.js"); +var error = utils.debug('components:text:error'); +var shaders = coreShader.shaders; +var warn = utils.debug('components:text:warn'); + +// 1 to match other A-Frame default widths. +var DEFAULT_WIDTH = 1; + +// @bryik set anisotropy to 16. Improves look of large amounts of text when viewed from angle. +var MAX_ANISOTROPY = 16; +var FONT_BASE_URL = 'https://cdn.aframe.io/fonts/'; +var FONTS = { + aileronsemibold: FONT_BASE_URL + 'Aileron-Semibold.fnt', + dejavu: FONT_BASE_URL + 'DejaVu-sdf.fnt', + exo2bold: FONT_BASE_URL + 'Exo2Bold.fnt', + exo2semibold: FONT_BASE_URL + 'Exo2SemiBold.fnt', + kelsonsans: FONT_BASE_URL + 'KelsonSans.fnt', + monoid: FONT_BASE_URL + 'Monoid.fnt', + mozillavr: FONT_BASE_URL + 'mozillavr.fnt', + roboto: FONT_BASE_URL + 'Roboto-msdf.json', + sourcecodepro: FONT_BASE_URL + 'SourceCodePro.fnt' +}; +var MSDF_FONTS = ['roboto']; +var DEFAULT_FONT = 'roboto'; +module.exports.FONTS = FONTS; +var cache = new PromiseCache(); +var fontWidthFactors = {}; +var textures = {}; + +// Regular expression for detecting a URLs with a protocol prefix. +var protocolRe = /^\w+:/; + +/** + * SDF-based text component. + * Based on https://github.com/Jam3/three-bmfont-text. + * + * All the stock fonts are for the `sdf` registered shader, an improved version of jam3's + * original `sdf` shader. + */ +module.exports.Component = registerComponent('text', { + multiple: true, + schema: { + align: { + type: 'string', + default: 'left', + oneOf: ['left', 'right', 'center'] + }, + alphaTest: { + default: 0.5 + }, + // `anchor` defaults to center to match geometries. + anchor: { + default: 'center', + oneOf: ['left', 'right', 'center', 'align'] + }, + baseline: { + default: 'center', + oneOf: ['top', 'center', 'bottom'] + }, + color: { + type: 'color', + default: '#FFF' + }, + font: { + type: 'string', + default: DEFAULT_FONT + }, + // `fontImage` defaults to the font name as a .png (e.g., mozillavr.fnt -> mozillavr.png). + fontImage: { + type: 'string' + }, + // `height` has no default, will be populated at layout. + height: { + type: 'number' + }, + letterSpacing: { + type: 'number', + default: 0 + }, + // `lineHeight` defaults to font's `lineHeight` value. + lineHeight: { + type: 'number' + }, + // `negate` must be true for fonts generated with older versions of msdfgen (white background). + negate: { + type: 'boolean', + default: true + }, + opacity: { + type: 'number', + default: 1.0 + }, + shader: { + default: 'sdf', + oneOf: shaders + }, + side: { + default: 'front', + oneOf: ['front', 'back', 'double'] + }, + tabSize: { + default: 4 + }, + transparent: { + default: true + }, + value: { + type: 'string' + }, + whiteSpace: { + default: 'normal', + oneOf: ['normal', 'pre', 'nowrap'] + }, + // `width` defaults to geometry width if present, else `DEFAULT_WIDTH`. + width: { + type: 'number' + }, + // `wrapCount` units are about one default font character. Wrap roughly at this number. + wrapCount: { + type: 'number', + default: 40 + }, + // `wrapPixels` will wrap using bmfont pixel units (e.g., dejavu's is 32 pixels). + wrapPixels: { + type: 'number' + }, + // `xOffset` to add padding. + xOffset: { + type: 'number', + default: 0 + }, + // `yOffset` to adjust generated fonts from tools that may have incorrect metrics. + yOffset: { + type: 'number', + default: 0 + }, + // `zOffset` will provide a small z offset to avoid z-fighting. + zOffset: { + type: 'number', + default: 0.001 + } + }, + init: function () { + this.shaderData = {}; + this.geometry = createTextGeometry(); + this.createOrUpdateMaterial(); + }, + update: function (oldData) { + var data = this.data; + var font = this.currentFont; + if (textures[data.font]) { + this.texture = textures[data.font]; + } else { + // Create texture per font. + this.texture = textures[data.font] = new THREE.Texture(); + this.texture.anisotropy = MAX_ANISOTROPY; + } + + // Update material. + this.createOrUpdateMaterial(); + + // New font. `updateFont` will later change data and layout. + if (oldData.font !== data.font) { + this.updateFont(); + return; + } + + // Update geometry and layout. + if (font) { + this.updateGeometry(this.geometry, font); + this.updateLayout(); + } + }, + /** + * Clean up geometry, material, texture, mesh, objects. + */ + remove: function () { + this.geometry.dispose(); + this.geometry = null; + this.el.removeObject3D(this.attrName); + this.material.dispose(); + this.material = null; + this.texture.dispose(); + this.texture = null; + if (this.shaderObject) { + delete this.shaderObject; + } + }, + /** + * Update the shader of the material. + */ + createOrUpdateMaterial: function () { + var data = this.data; + var hasChangedShader; + var material = this.material; + var NewShader; + var shaderData = this.shaderData; + var shaderName; + + // Infer shader if using a stock font (or from `-msdf` filename convention). + shaderName = data.shader; + if (MSDF_FONTS.indexOf(data.font) !== -1 || data.font.indexOf('-msdf.') >= 0) { + shaderName = 'msdf'; + } else if (data.font in FONTS && MSDF_FONTS.indexOf(data.font) === -1) { + shaderName = 'sdf'; + } + hasChangedShader = (this.shaderObject && this.shaderObject.name) !== shaderName; + shaderData.alphaTest = data.alphaTest; + shaderData.color = data.color; + shaderData.map = this.texture; + shaderData.opacity = data.opacity; + shaderData.side = parseSide(data.side); + shaderData.transparent = data.transparent; + shaderData.negate = data.negate; + + // Shader has not changed, do an update. + if (!hasChangedShader) { + // Update shader material. + this.shaderObject.update(shaderData); + // Apparently, was not set on `init` nor `update`. + material.transparent = shaderData.transparent; + material.side = shaderData.side; + return; + } + + // Shader has changed. Create a shader material. + NewShader = createShader(this.el, shaderName, shaderData); + this.material = NewShader.material; + this.shaderObject = NewShader.shader; + + // Set new shader material. + this.material.side = shaderData.side; + if (this.mesh) { + this.mesh.material = this.material; + } + }, + /** + * Load font for geometry, load font image for material, and apply. + */ + updateFont: function () { + var data = this.data; + var el = this.el; + var fontSrc; + var geometry = this.geometry; + var self = this; + if (!data.font) { + warn('No font specified. Using the default font.'); + } + + // Make invisible during font swap. + if (this.mesh) { + this.mesh.visible = false; + } + + // Look up font URL to use, and perform cached load. + fontSrc = this.lookupFont(data.font || DEFAULT_FONT) || data.font; + cache.get(fontSrc, function doLoadFont() { + return loadFont(fontSrc, data.yOffset); + }).then(function setFont(font) { + var fontImgSrc; + if (font.pages.length !== 1) { + throw new Error('Currently only single-page bitmap fonts are supported.'); + } + if (!fontWidthFactors[fontSrc]) { + font.widthFactor = fontWidthFactors[font] = computeFontWidthFactor(font); + } + self.currentFont = font; + // Look up font image URL to use, and perform cached load. + fontImgSrc = self.getFontImageSrc(); + cache.get(fontImgSrc, function () { + return loadTexture(fontImgSrc); + }).then(function (image) { + // Make mesh visible and apply font image as texture. + var texture = self.texture; + // The component may have been removed at this point and texture will + // be null. This happens mainly while executing the tests, + // in this case we just return. + if (!texture) return; + texture.image = image; + texture.needsUpdate = true; + textures[data.font] = texture; + self.texture = texture; + self.initMesh(); + self.currentFont = font; + // Update geometry given font metrics. + self.updateGeometry(geometry, font); + self.updateLayout(); + self.mesh.visible = true; + el.emit('textfontset', { + font: data.font, + fontObj: font + }); + }).catch(function (err) { + error(err.message); + error(err.stack); + }); + }).catch(function (err) { + error(err.message); + error(err.stack); + }); + }, + initMesh: function () { + if (this.mesh) { + return; + } + this.mesh = new THREE.Mesh(this.geometry, this.material); + this.el.setObject3D(this.attrName, this.mesh); + }, + getFontImageSrc: function () { + if (this.data.fontImage) { + return this.data.fontImage; + } + var fontSrc = this.lookupFont(this.data.font || DEFAULT_FONT) || this.data.font; + var imageSrc = this.currentFont.pages[0]; + // If the image URL contains a non-HTTP(S) protocol, assume it's an absolute + // path on disk and try to infer the path from the font source instead. + if (imageSrc.match(protocolRe) && imageSrc.indexOf('http') !== 0) { + return fontSrc.replace(/(\.fnt)|(\.json)/, '.png'); + } + return THREE.LoaderUtils.extractUrlBase(fontSrc) + imageSrc; + }, + /** + * Update layout with anchor, alignment, baseline, and considering any meshes. + */ + updateLayout: function () { + var anchor; + var baseline; + var el = this.el; + var data = this.data; + var geometry = this.geometry; + var geometryComponent; + var height; + var layout; + var mesh = this.mesh; + var textRenderWidth; + var textScale; + var width; + var x; + var y; + if (!mesh || !geometry.layout) { + return; + } + + // Determine width to use (defined width, geometry's width, or default width). + geometryComponent = el.getAttribute('geometry'); + width = data.width || geometryComponent && geometryComponent.width || DEFAULT_WIDTH; + + // Determine wrap pixel count. Either specified or by experimental fudge factor. + // Note that experimental factor will never be correct for variable width fonts. + textRenderWidth = computeWidth(data.wrapPixels, data.wrapCount, this.currentFont.widthFactor); + textScale = width / textRenderWidth; + + // Determine height to use. + layout = geometry.layout; + height = textScale * (layout.height + layout.descender); + + // Update geometry dimensions to match text layout if width and height are set to 0. + // For example, scales a plane to fit text. + if (geometryComponent && geometryComponent.primitive === 'plane') { + if (!geometryComponent.width) { + el.setAttribute('geometry', 'width', width); + } + if (!geometryComponent.height) { + el.setAttribute('geometry', 'height', height); + } + } + + // Calculate X position to anchor text left, center, or right. + anchor = data.anchor === 'align' ? data.align : data.anchor; + if (anchor === 'left') { + x = 0; + } else if (anchor === 'right') { + x = -1 * layout.width; + } else if (anchor === 'center') { + x = -1 * layout.width / 2; + } else { + throw new TypeError('Invalid text.anchor property value', anchor); + } + + // Calculate Y position to anchor text top, center, or bottom. + baseline = data.baseline; + if (baseline === 'bottom') { + y = 0; + } else if (baseline === 'top') { + y = -1 * layout.height + layout.ascender; + } else if (baseline === 'center') { + y = -1 * layout.height / 2; + } else { + throw new TypeError('Invalid text.baseline property value', baseline); + } + + // Position and scale mesh to apply layout. + mesh.position.x = x * textScale + data.xOffset; + mesh.position.y = y * textScale; + // Place text slightly in front to avoid Z-fighting. + mesh.position.z = data.zOffset; + mesh.scale.set(textScale, -1 * textScale, textScale); + }, + /** + * Grab font from the constant. + * Set as a method for test stubbing purposes. + */ + lookupFont: function (key) { + return FONTS[key]; + }, + /** + * Update the text geometry using `three-bmfont-text.update`. + */ + updateGeometry: function () { + var geometryUpdateBase = {}; + var geometryUpdateData = {}; + var newLineRegex = /\\n/g; + var tabRegex = /\\t/g; + return function (geometry, font) { + var data = this.data; + geometryUpdateData.font = font; + geometryUpdateData.lineHeight = data.lineHeight && isFinite(data.lineHeight) ? data.lineHeight : font.common.lineHeight; + geometryUpdateData.text = data.value.toString().replace(newLineRegex, '\n').replace(tabRegex, '\t'); + geometryUpdateData.width = computeWidth(data.wrapPixels, data.wrapCount, font.widthFactor); + geometry.update(utils.extend(geometryUpdateBase, data, geometryUpdateData)); + }; + }() +}); + +/** + * Due to using negative scale, we return the opposite side specified. + * https://github.com/mrdoob/three.js/pull/12787/ + */ +function parseSide(side) { + switch (side) { + case 'back': + { + return THREE.FrontSide; + } + case 'double': + { + return THREE.DoubleSide; + } + default: + { + return THREE.BackSide; + } + } +} + +/** + * @returns {Promise} + */ +function loadFont(src, yOffset) { + return new Promise(function (resolve, reject) { + loadBMFont(src, function (err, font) { + if (err) { + error('Error loading font', src); + reject(err); + return; + } + + // Fix negative Y offsets for Roboto MSDF font from tool. Experimentally determined. + if (src.indexOf('/Roboto-msdf.json') >= 0) { + yOffset = 30; + } + if (yOffset) { + font.chars.map(function doOffset(ch) { + ch.yoffset += yOffset; + }); + } + resolve(font); + }); + }); +} + +/** + * @returns {Promise} + */ +function loadTexture(src) { + return new Promise(function (resolve, reject) { + new THREE.ImageLoader().load(src, function (image) { + resolve(image); + }, undefined, function () { + error('Error loading font image', src); + reject(null); + }); + }); +} +function createShader(el, shaderName, data) { + var shader; + var shaderObject; + + // Set up Shader. + shaderObject = new shaders[shaderName].Shader(); + shaderObject.el = el; + shaderObject.init(data); + shaderObject.update(data); + + // Get material. + shader = shaderObject.material; + // Apparently, was not set on `init` nor `update`. + shader.transparent = data.transparent; + return { + material: shader, + shader: shaderObject + }; +} + +/** + * Determine wrap pixel count. Either specified or by experimental fudge factor. + * Note that experimental factor will never be correct for variable width fonts. + */ +function computeWidth(wrapPixels, wrapCount, widthFactor) { + return wrapPixels || (0.5 + wrapCount) * widthFactor; +} + +/** + * Compute default font width factor to use. + */ +function computeFontWidthFactor(font) { + var sum = 0; + var digitsum = 0; + var digits = 0; + font.chars.map(function (ch) { + sum += ch.xadvance; + if (ch.id >= 48 && ch.id <= 57) { + digits++; + digitsum += ch.xadvance; + } + }); + return digits ? digitsum / digits : sum / font.chars.length; +} + +/** + * Get or create a promise given a key and promise generator. + * @todo Move to a utility and use in other parts of A-Frame. + */ +function PromiseCache() { + var cache = this.cache = {}; + this.get = function (key, promiseGenerator) { + if (key in cache) { + return cache[key]; + } + cache[key] = promiseGenerator(); + return cache[key]; + }; +} + +/***/ }), + +/***/ "./src/components/tracked-controls-webvr.js": +/*!**************************************************!*\ + !*** ./src/components/tracked-controls-webvr.js ***! + \**************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var controllerUtils = __webpack_require__(/*! ../utils/tracked-controls */ "./src/utils/tracked-controls.js"); +var DEFAULT_CAMERA_HEIGHT = (__webpack_require__(/*! ../constants */ "./src/constants/index.js").DEFAULT_CAMERA_HEIGHT); +var THREE = __webpack_require__(/*! ../lib/three */ "./src/lib/three.js"); +var DEFAULT_HANDEDNESS = (__webpack_require__(/*! ../constants */ "./src/constants/index.js").DEFAULT_HANDEDNESS); +// Vector from eyes to elbow (divided by user height). +var EYES_TO_ELBOW = { + x: 0.175, + y: -0.3, + z: -0.03 +}; +// Vector from eyes to elbow (divided by user height). +var FOREARM = { + x: 0, + y: 0, + z: -0.175 +}; + +// Due to unfortunate name collision, add empty touches array to avoid Daydream error. +var EMPTY_DAYDREAM_TOUCHES = { + touches: [] +}; +var EVENTS = { + AXISMOVE: 'axismove', + BUTTONCHANGED: 'buttonchanged', + BUTTONDOWN: 'buttondown', + BUTTONUP: 'buttonup', + TOUCHSTART: 'touchstart', + TOUCHEND: 'touchend' +}; + +/** + * Tracked controls component. + * Wrap the gamepad API for pose and button states. + * Select the appropriate controller and apply pose to the entity. + * Observe button states and emit appropriate events. + * + * @property {number} controller - Index of controller in array returned by Gamepad API. + * Only used if hand property is not set. + * @property {string} id - Selected controller among those returned by Gamepad API. + * @property {number} hand - If multiple controllers found with id, choose the one with the + * given value for hand. If set, we ignore 'controller' property + */ +module.exports.Component = registerComponent('tracked-controls-webvr', { + schema: { + autoHide: { + default: true + }, + controller: { + default: 0 + }, + id: { + type: 'string', + default: '' + }, + hand: { + type: 'string', + default: '' + }, + idPrefix: { + type: 'string', + default: '' + }, + orientationOffset: { + type: 'vec3' + }, + // Arm model parameters when not 6DoF. + armModel: { + default: false + }, + headElement: { + type: 'selector' + } + }, + init: function () { + // Copy variables back to tracked-controls for backwards compatibility. + // Some 3rd components rely on them. + this.axis = this.el.components['tracked-controls'].axis = [0, 0, 0]; + this.buttonStates = this.el.components['tracked-controls'].buttonStates = {}; + this.changedAxes = []; + this.targetControllerNumber = this.data.controller; + this.axisMoveEventDetail = { + axis: this.axis, + changed: this.changedAxes + }; + this.deltaControllerPosition = new THREE.Vector3(); + this.controllerQuaternion = new THREE.Quaternion(); + this.controllerEuler = new THREE.Euler(); + this.updateGamepad(); + this.buttonEventDetails = {}; + }, + tick: function (time, delta) { + var mesh = this.el.getObject3D('mesh'); + // Update mesh animations. + if (mesh && mesh.update) { + mesh.update(delta / 1000); + } + this.updateGamepad(); + this.updatePose(); + this.updateButtons(); + }, + /** + * Return default user height to use for non-6DOF arm model. + */ + defaultUserHeight: function () { + return DEFAULT_CAMERA_HEIGHT; + }, + /** + * Return head element to use for non-6DOF arm model. + */ + getHeadElement: function () { + return this.data.headElement || this.el.sceneEl.camera.el; + }, + /** + * Handle update controller match criteria (such as `id`, `idPrefix`, `hand`, `controller`) + */ + updateGamepad: function () { + var data = this.data; + var controller = controllerUtils.findMatchingControllerWebVR(this.system.controllers, data.id, data.idPrefix, data.hand, data.controller); + this.controller = controller; + // Legacy handle to the controller for old components. + this.el.components['tracked-controls'].controller = controller; + if (this.data.autoHide) { + this.el.object3D.visible = !!this.controller; + } + }, + /** + * Applies an artificial arm model to simulate elbow to wrist positioning + * based on the orientation of the controller. + * + * @param {object} controllerPosition - Existing vector to update with controller position. + */ + applyArmModel: function (controllerPosition) { + // Use controllerPosition and deltaControllerPosition to avoid creating variables. + var controller = this.controller; + var controllerEuler = this.controllerEuler; + var controllerQuaternion = this.controllerQuaternion; + var deltaControllerPosition = this.deltaControllerPosition; + var hand; + var headEl; + var headObject3D; + var pose; + var userHeight; + headEl = this.getHeadElement(); + headObject3D = headEl.object3D; + userHeight = this.defaultUserHeight(); + pose = controller.pose; + hand = (controller ? controller.hand : undefined) || DEFAULT_HANDEDNESS; + + // Use camera position as head position. + controllerPosition.copy(headObject3D.position); + // Set offset for degenerate "arm model" to elbow. + deltaControllerPosition.set(EYES_TO_ELBOW.x * (hand === 'left' ? -1 : hand === 'right' ? 1 : 0), EYES_TO_ELBOW.y, + // Lower than our eyes. + EYES_TO_ELBOW.z); // Slightly out in front. + // Scale offset by user height. + deltaControllerPosition.multiplyScalar(userHeight); + // Apply camera Y rotation (not X or Z, so you can look down at your hand). + deltaControllerPosition.applyAxisAngle(headObject3D.up, headObject3D.rotation.y); + // Apply rotated offset to position. + controllerPosition.add(deltaControllerPosition); + + // Set offset for degenerate "arm model" forearm. Forearm sticking out from elbow. + deltaControllerPosition.set(FOREARM.x, FOREARM.y, FOREARM.z); + // Scale offset by user height. + deltaControllerPosition.multiplyScalar(userHeight); + // Apply controller X/Y rotation (tilting up/down/left/right is usually moving the arm). + if (pose.orientation) { + controllerQuaternion.fromArray(pose.orientation); + } else { + controllerQuaternion.copy(headObject3D.quaternion); + } + controllerEuler.setFromQuaternion(controllerQuaternion); + controllerEuler.set(controllerEuler.x, controllerEuler.y, 0); + deltaControllerPosition.applyEuler(controllerEuler); + // Apply rotated offset to position. + controllerPosition.add(deltaControllerPosition); + }, + /** + * Read pose from controller (from Gamepad API), apply transforms, apply to entity. + */ + updatePose: function () { + var controller = this.controller; + var data = this.data; + var object3D = this.el.object3D; + var pose; + var vrDisplay = this.system.vrDisplay; + var standingMatrix; + if (!controller) { + return; + } + + // Compose pose from Gamepad. + pose = controller.pose; + if (pose.position) { + object3D.position.fromArray(pose.position); + } else { + // Controller not 6DOF, apply arm model. + if (data.armModel) { + this.applyArmModel(object3D.position); + } + } + if (pose.orientation) { + object3D.quaternion.fromArray(pose.orientation); + } + + // Apply transforms, if 6DOF and in VR. + if (vrDisplay && pose.position) { + standingMatrix = this.el.sceneEl.renderer.xr.getStandingMatrix(); + object3D.matrix.compose(object3D.position, object3D.quaternion, object3D.scale); + object3D.matrix.multiplyMatrices(standingMatrix, object3D.matrix); + object3D.matrix.decompose(object3D.position, object3D.quaternion, object3D.scale); + } + object3D.rotateX(this.data.orientationOffset.x * THREE.MathUtils.DEG2RAD); + object3D.rotateY(this.data.orientationOffset.y * THREE.MathUtils.DEG2RAD); + object3D.rotateZ(this.data.orientationOffset.z * THREE.MathUtils.DEG2RAD); + }, + /** + * Handle button changes including axes, presses, touches, values. + */ + updateButtons: function () { + var buttonState; + var controller = this.controller; + var id; + if (!controller) { + return; + } + + // Check every button. + for (id = 0; id < controller.buttons.length; ++id) { + // Initialize button state. + if (!this.buttonStates[id]) { + this.buttonStates[id] = { + pressed: false, + touched: false, + value: 0 + }; + } + if (!this.buttonEventDetails[id]) { + this.buttonEventDetails[id] = { + id: id, + state: this.buttonStates[id] + }; + } + buttonState = controller.buttons[id]; + this.handleButton(id, buttonState); + } + // Check axes. + this.handleAxes(); + }, + /** + * Handle presses and touches for a single button. + * + * @param {number} id - Index of button in Gamepad button array. + * @param {number} buttonState - Value of button state from 0 to 1. + * @returns {boolean} Whether button has changed in any way. + */ + handleButton: function (id, buttonState) { + var changed; + changed = this.handlePress(id, buttonState) | this.handleTouch(id, buttonState) | this.handleValue(id, buttonState); + if (!changed) { + return false; + } + this.el.emit(EVENTS.BUTTONCHANGED, this.buttonEventDetails[id], false); + return true; + }, + /** + * An axis is an array of values from -1 (up, left) to 1 (down, right). + * Compare each component of the axis to the previous value to determine change. + * + * @returns {boolean} Whether axes changed. + */ + handleAxes: function () { + var changed = false; + var controllerAxes = this.controller.axes; + var i; + var previousAxis = this.axis; + var changedAxes = this.changedAxes; + + // Check if axis changed. + this.changedAxes.splice(0, this.changedAxes.length); + for (i = 0; i < controllerAxes.length; ++i) { + changedAxes.push(previousAxis[i] !== controllerAxes[i]); + if (changedAxes[i]) { + changed = true; + } + } + if (!changed) { + return false; + } + this.axis.splice(0, this.axis.length); + for (i = 0; i < controllerAxes.length; i++) { + this.axis.push(controllerAxes[i]); + } + this.el.emit(EVENTS.AXISMOVE, this.axisMoveEventDetail, false); + return true; + }, + /** + * Determine whether a button press has occured and emit events as appropriate. + * + * @param {string} id - ID of the button to check. + * @param {object} buttonState - State of the button to check. + * @returns {boolean} Whether button press state changed. + */ + handlePress: function (id, buttonState) { + var evtName; + var previousButtonState = this.buttonStates[id]; + + // Not changed. + if (buttonState.pressed === previousButtonState.pressed) { + return false; + } + evtName = buttonState.pressed ? EVENTS.BUTTONDOWN : EVENTS.BUTTONUP; + this.el.emit(evtName, this.buttonEventDetails[id], false); + previousButtonState.pressed = buttonState.pressed; + return true; + }, + /** + * Determine whether a button touch has occured and emit events as appropriate. + * + * @param {string} id - ID of the button to check. + * @param {object} buttonState - State of the button to check. + * @returns {boolean} Whether button touch state changed. + */ + handleTouch: function (id, buttonState) { + var evtName; + var previousButtonState = this.buttonStates[id]; + + // Not changed. + if (buttonState.touched === previousButtonState.touched) { + return false; + } + evtName = buttonState.touched ? EVENTS.TOUCHSTART : EVENTS.TOUCHEND; + this.el.emit(evtName, this.buttonEventDetails[id], false, EMPTY_DAYDREAM_TOUCHES); + previousButtonState.touched = buttonState.touched; + return true; + }, + /** + * Determine whether a button value has changed. + * + * @param {string} id - Id of the button to check. + * @param {object} buttonState - State of the button to check. + * @returns {boolean} Whether button value changed. + */ + handleValue: function (id, buttonState) { + var previousButtonState = this.buttonStates[id]; + + // Not changed. + if (buttonState.value === previousButtonState.value) { + return false; + } + previousButtonState.value = buttonState.value; + return true; + } +}); + +/***/ }), + +/***/ "./src/components/tracked-controls-webxr.js": +/*!**************************************************!*\ + !*** ./src/components/tracked-controls-webxr.js ***! + \**************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var controllerUtils = __webpack_require__(/*! ../utils/tracked-controls */ "./src/utils/tracked-controls.js"); +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var EVENTS = { + AXISMOVE: 'axismove', + BUTTONCHANGED: 'buttonchanged', + BUTTONDOWN: 'buttondown', + BUTTONUP: 'buttonup', + TOUCHSTART: 'touchstart', + TOUCHEND: 'touchend' +}; +module.exports.Component = registerComponent('tracked-controls-webxr', { + schema: { + id: { + type: 'string', + default: '' + }, + hand: { + type: 'string', + default: '' + }, + handTrackingEnabled: { + default: false + }, + index: { + type: 'int', + default: -1 + }, + iterateControllerProfiles: { + default: false + }, + space: { + type: 'string', + oneOf: ['targetRaySpace', 'gripSpace'], + default: 'gripSpace' + } + }, + init: function () { + this.updateController = this.updateController.bind(this); + this.buttonEventDetails = {}; + this.buttonStates = this.el.components['tracked-controls'].buttonStates = {}; + this.axis = this.el.components['tracked-controls'].axis = [0, 0, 0]; + this.changedAxes = []; + this.axisMoveEventDetail = { + axis: this.axis, + changed: this.changedAxes + }; + }, + update: function () { + this.updateController(); + }, + play: function () { + var sceneEl = this.el.sceneEl; + this.updateController(); + sceneEl.addEventListener('controllersupdated', this.updateController); + }, + pause: function () { + var sceneEl = this.el.sceneEl; + sceneEl.removeEventListener('controllersupdated', this.updateController); + }, + isControllerPresent: function (evt) { + if (!this.controller || this.controller.gamepad) { + return false; + } + if (evt.inputSource.handedness !== 'none' && evt.inputSource.handedness !== this.data.hand) { + return false; + } + return true; + }, + /** + * Handle update controller match criteria (such as `id`, `idPrefix`, `hand`, `controller`) + */ + updateController: function () { + this.controller = controllerUtils.findMatchingControllerWebXR(this.system.controllers, this.data.id, this.data.hand, this.data.index, this.data.iterateControllerProfiles, this.data.handTrackingEnabled); + // Legacy handle to the controller for old components. + this.el.components['tracked-controls'].controller = this.controller; + if (this.data.autoHide) { + this.el.object3D.visible = !!this.controller; + } + }, + tick: function () { + var sceneEl = this.el.sceneEl; + var controller = this.controller; + var frame = sceneEl.frame; + if (!controller || !sceneEl.frame || !this.system.referenceSpace) { + return; + } + if (!controller.hand) { + this.pose = frame.getPose(controller[this.data.space], this.system.referenceSpace); + this.updatePose(); + this.updateButtons(); + } + }, + updatePose: function () { + var object3D = this.el.object3D; + var pose = this.pose; + if (!pose) { + return; + } + object3D.matrix.elements = pose.transform.matrix; + object3D.matrix.decompose(object3D.position, object3D.rotation, object3D.scale); + }, + /** + * Handle button changes including axes, presses, touches, values. + */ + updateButtons: function () { + var buttonState; + var id; + var controller = this.controller; + var gamepad; + if (!controller || !controller.gamepad) { + return; + } + gamepad = controller.gamepad; + // Check every button. + for (id = 0; id < gamepad.buttons.length; ++id) { + // Initialize button state. + if (!this.buttonStates[id]) { + this.buttonStates[id] = { + pressed: false, + touched: false, + value: 0 + }; + } + if (!this.buttonEventDetails[id]) { + this.buttonEventDetails[id] = { + id: id, + state: this.buttonStates[id] + }; + } + buttonState = gamepad.buttons[id]; + this.handleButton(id, buttonState); + } + // Check axes. + this.handleAxes(); + }, + /** + * Handle presses and touches for a single button. + * + * @param {number} id - Index of button in Gamepad button array. + * @param {number} buttonState - Value of button state from 0 to 1. + * @returns {boolean} Whether button has changed in any way. + */ + handleButton: function (id, buttonState) { + var changed; + changed = this.handlePress(id, buttonState) | this.handleTouch(id, buttonState) | this.handleValue(id, buttonState); + if (!changed) { + return false; + } + this.el.emit(EVENTS.BUTTONCHANGED, this.buttonEventDetails[id], false); + return true; + }, + /** + * An axis is an array of values from -1 (up, left) to 1 (down, right). + * Compare each component of the axis to the previous value to determine change. + * + * @returns {boolean} Whether axes changed. + */ + handleAxes: function () { + var changed = false; + var controllerAxes = this.controller.gamepad.axes; + var i; + var previousAxis = this.axis; + var changedAxes = this.changedAxes; + + // Check if axis changed. + this.changedAxes.splice(0, this.changedAxes.length); + for (i = 0; i < controllerAxes.length; ++i) { + changedAxes.push(previousAxis[i] !== controllerAxes[i]); + if (changedAxes[i]) { + changed = true; + } + } + if (!changed) { + return false; + } + this.axis.splice(0, this.axis.length); + for (i = 0; i < controllerAxes.length; i++) { + this.axis.push(controllerAxes[i]); + } + this.el.emit(EVENTS.AXISMOVE, this.axisMoveEventDetail, false); + return true; + }, + /** + * Determine whether a button press has occured and emit events as appropriate. + * + * @param {string} id - ID of the button to check. + * @param {object} buttonState - State of the button to check. + * @returns {boolean} Whether button press state changed. + */ + handlePress: function (id, buttonState) { + var evtName; + var previousButtonState = this.buttonStates[id]; + + // Not changed. + if (buttonState.pressed === previousButtonState.pressed) { + return false; + } + evtName = buttonState.pressed ? EVENTS.BUTTONDOWN : EVENTS.BUTTONUP; + this.el.emit(evtName, this.buttonEventDetails[id], false); + previousButtonState.pressed = buttonState.pressed; + return true; + }, + /** + * Determine whether a button touch has occured and emit events as appropriate. + * + * @param {string} id - ID of the button to check. + * @param {object} buttonState - State of the button to check. + * @returns {boolean} Whether button touch state changed. + */ + handleTouch: function (id, buttonState) { + var evtName; + var previousButtonState = this.buttonStates[id]; + + // Not changed. + if (buttonState.touched === previousButtonState.touched) { + return false; + } + evtName = buttonState.touched ? EVENTS.TOUCHSTART : EVENTS.TOUCHEND; + this.el.emit(evtName, this.buttonEventDetails[id], false); + previousButtonState.touched = buttonState.touched; + return true; + }, + /** + * Determine whether a button value has changed. + * + * @param {string} id - Id of the button to check. + * @param {object} buttonState - State of the button to check. + * @returns {boolean} Whether button value changed. + */ + handleValue: function (id, buttonState) { + var previousButtonState = this.buttonStates[id]; + + // Not changed. + if (buttonState.value === previousButtonState.value) { + return false; + } + previousButtonState.value = buttonState.value; + return true; + } +}); + +/***/ }), + +/***/ "./src/components/tracked-controls.js": +/*!********************************************!*\ + !*** ./src/components/tracked-controls.js ***! + \********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); + +/** + * Tracked controls. + * Abstract controls that decide if the WebVR or WebXR version is going to be applied. + * + * @property {number} controller - Index of controller in array returned by Gamepad API. + * Only used if hand property is not set. + * @property {string} id - Selected controller among those returned by Gamepad API. + * @property {number} hand - If multiple controllers found with id, choose the one with the + * given value for hand. If set, we ignore 'controller' property + */ +module.exports.Component = registerComponent('tracked-controls', { + schema: { + autoHide: { + default: true + }, + controller: { + default: -1 + }, + id: { + type: 'string', + default: '' + }, + hand: { + type: 'string', + default: '' + }, + idPrefix: { + type: 'string', + default: '' + }, + handTrackingEnabled: { + default: false + }, + orientationOffset: { + type: 'vec3' + }, + // Arm model parameters when not 6DoF. + armModel: { + default: false + }, + headElement: { + type: 'selector' + }, + iterateControllerProfiles: { + default: false + }, + space: { + type: 'string', + oneOf: ['targetRaySpace', 'gripSpace'], + default: 'targetRaySpace' + } + }, + update: function () { + var data = this.data; + var el = this.el; + if (el.sceneEl.hasWebXR) { + el.setAttribute('tracked-controls-webxr', { + id: data.id, + hand: data.hand, + index: data.controller, + iterateControllerProfiles: data.iterateControllerProfiles, + handTrackingEnabled: data.handTrackingEnabled, + space: data.space + }); + } else { + el.setAttribute('tracked-controls-webvr', data); + } + } +}); + +/***/ }), + +/***/ "./src/components/valve-index-controls.js": +/*!************************************************!*\ + !*** ./src/components/valve-index-controls.js ***! + \************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var bind = __webpack_require__(/*! ../utils/bind */ "./src/utils/bind.js"); +var THREE = __webpack_require__(/*! ../lib/three */ "./src/lib/three.js"); +var trackedControlsUtils = __webpack_require__(/*! ../utils/tracked-controls */ "./src/utils/tracked-controls.js"); +var checkControllerPresentAndSetup = trackedControlsUtils.checkControllerPresentAndSetup; +var emitIfAxesChanged = trackedControlsUtils.emitIfAxesChanged; +var onButtonEvent = trackedControlsUtils.onButtonEvent; +var INDEX_CONTROLLER_MODEL_BASE_URL = 'https://cdn.aframe.io/controllers/valve/index/valve-index-'; +var INDEX_CONTROLLER_MODEL_URL = { + left: INDEX_CONTROLLER_MODEL_BASE_URL + 'left.glb', + right: INDEX_CONTROLLER_MODEL_BASE_URL + 'right.glb' +}; +var GAMEPAD_ID_PREFIX = 'valve'; +var isWebXRAvailable = (__webpack_require__(/*! ../utils/ */ "./src/utils/index.js").device.isWebXRAvailable); +var INDEX_CONTROLLER_POSITION_OFFSET_WEBVR = { + left: { + x: -0.00023692678902063457, + y: 0.04724540367838371, + z: -0.061959880395271096 + }, + right: { + x: 0.002471558599671131, + y: 0.055765208987076195, + z: -0.061068168708348844 + } +}; +var INDEX_CONTROLLER_POSITION_OFFSET_WEBXR = { + left: { + x: 0, + y: -0.05, + z: 0.06 + }, + right: { + x: 0, + y: -0.05, + z: 0.06 + } +}; +var INDEX_CONTROLLER_ROTATION_OFFSET_WEBVR = { + left: { + _x: 0.692295102620542, + _y: -0.0627618864318427, + _z: -0.06265893149611756, + _order: 'XYZ' + }, + right: { + _x: 0.6484021229942998, + _y: -0.032563619881892894, + _z: -0.1327973171917482, + _order: 'XYZ' + } +}; +var INDEX_CONTROLLER_ROTATION_OFFSET_WEBXR = { + left: { + _x: Math.PI / 3, + _y: 0, + _z: 0, + _order: 'XYZ' + }, + right: { + _x: Math.PI / 3, + _y: 0, + _z: 0, + _order: 'XYZ' + } +}; +var INDEX_CONTROLLER_ROTATION_OFFSET = isWebXRAvailable ? INDEX_CONTROLLER_ROTATION_OFFSET_WEBXR : INDEX_CONTROLLER_ROTATION_OFFSET_WEBVR; +var INDEX_CONTROLLER_POSITION_OFFSET = isWebXRAvailable ? INDEX_CONTROLLER_POSITION_OFFSET_WEBXR : INDEX_CONTROLLER_POSITION_OFFSET_WEBVR; +/** + * Vive controls. + * Interface with Vive controllers and map Gamepad events to controller buttons: + * trackpad, trigger, grip, menu, system + * Load a controller model and highlight the pressed buttons. + */ +module.exports.Component = registerComponent('valve-index-controls', { + schema: { + hand: { + default: 'left' + }, + buttonColor: { + type: 'color', + default: '#FAFAFA' + }, + // Off-white. + buttonHighlightColor: { + type: 'color', + default: '#22D1EE' + }, + // Light blue. + model: { + default: true + }, + orientationOffset: { + type: 'vec3' + } + }, + mapping: { + axes: { + trackpad: [0, 1], + thumbstick: [2, 3] + }, + buttons: ['trigger', 'grip', 'trackpad', 'thumbstick', 'abutton'] + }, + init: function () { + var self = this; + this.controllerPresent = false; + this.lastControllerCheck = 0; + this.onButtonChanged = bind(this.onButtonChanged, this); + this.onButtonDown = function (evt) { + onButtonEvent(evt.detail.id, 'down', self); + }; + this.onButtonUp = function (evt) { + onButtonEvent(evt.detail.id, 'up', self); + }; + this.onButtonTouchEnd = function (evt) { + onButtonEvent(evt.detail.id, 'touchend', self); + }; + this.onButtonTouchStart = function (evt) { + onButtonEvent(evt.detail.id, 'touchstart', self); + }; + this.previousButtonValues = {}; + this.rendererSystem = this.el.sceneEl.systems.renderer; + this.bindMethods(); + }, + play: function () { + this.checkIfControllerPresent(); + this.addControllersUpdateListener(); + }, + pause: function () { + this.removeEventListeners(); + this.removeControllersUpdateListener(); + }, + bindMethods: function () { + this.onModelLoaded = bind(this.onModelLoaded, this); + this.onControllersUpdate = bind(this.onControllersUpdate, this); + this.checkIfControllerPresent = bind(this.checkIfControllerPresent, this); + this.removeControllersUpdateListener = bind(this.removeControllersUpdateListener, this); + this.onAxisMoved = bind(this.onAxisMoved, this); + }, + addEventListeners: function () { + var el = this.el; + el.addEventListener('buttonchanged', this.onButtonChanged); + el.addEventListener('buttondown', this.onButtonDown); + el.addEventListener('buttonup', this.onButtonUp); + el.addEventListener('touchend', this.onButtonTouchEnd); + el.addEventListener('touchstart', this.onButtonTouchStart); + el.addEventListener('model-loaded', this.onModelLoaded); + el.addEventListener('axismove', this.onAxisMoved); + this.controllerEventsActive = true; + }, + removeEventListeners: function () { + var el = this.el; + el.removeEventListener('buttonchanged', this.onButtonChanged); + el.removeEventListener('buttondown', this.onButtonDown); + el.removeEventListener('buttonup', this.onButtonUp); + el.removeEventListener('touchend', this.onButtonTouchEnd); + el.removeEventListener('touchstart', this.onButtonTouchStart); + el.removeEventListener('model-loaded', this.onModelLoaded); + el.removeEventListener('axismove', this.onAxisMoved); + this.controllerEventsActive = false; + }, + /** + * Once OpenVR returns correct hand data in supporting browsers, we can use hand property. + * var isPresent = checkControllerPresentAndSetup(this.el.sceneEl, GAMEPAD_ID_PREFIX, + { hand: data.hand }); + * Until then, use hardcoded index. + */ + checkIfControllerPresent: function () { + var data = this.data; + var controllerIndex = data.hand === 'right' ? 0 : data.hand === 'left' ? 1 : 2; + checkControllerPresentAndSetup(this, GAMEPAD_ID_PREFIX, { + index: controllerIndex, + iterateControllerProfiles: true, + hand: data.hand + }); + }, + injectTrackedControls: function () { + var el = this.el; + var data = this.data; + + // If we have an OpenVR Gamepad, use the fixed mapping. + el.setAttribute('tracked-controls', { + idPrefix: GAMEPAD_ID_PREFIX, + // Hand IDs: 1 = right, 0 = left, 2 = anything else. + controller: data.hand === 'right' ? 1 : data.hand === 'left' ? 0 : 2, + hand: data.hand, + orientationOffset: data.orientationOffset + }); + this.loadModel(); + }, + loadModel: function () { + var data = this.data; + if (!data.model) { + return; + } + this.el.setAttribute('gltf-model', '' + INDEX_CONTROLLER_MODEL_URL[data.hand] + ''); + }, + addControllersUpdateListener: function () { + this.el.sceneEl.addEventListener('controllersupdated', this.onControllersUpdate, false); + }, + removeControllersUpdateListener: function () { + this.el.sceneEl.removeEventListener('controllersupdated', this.onControllersUpdate, false); + }, + onControllersUpdate: function () { + this.checkIfControllerPresent(); + }, + /** + * Rotate the trigger button based on how hard the trigger is pressed. + */ + onButtonChanged: function (evt) { + var button = this.mapping.buttons[evt.detail.id]; + var buttonMeshes = this.buttonMeshes; + var analogValue; + if (!button) { + return; + } + if (button === 'trigger') { + analogValue = evt.detail.state.value; + // Update trigger rotation depending on button value. + if (buttonMeshes && buttonMeshes.trigger) { + buttonMeshes.trigger.rotation.x = this.triggerOriginalRotationX - analogValue * (Math.PI / 40); + } + } + + // Pass along changed event with button state, using button mapping for convenience. + this.el.emit(button + 'changed', evt.detail.state); + }, + onModelLoaded: function (evt) { + var buttonMeshes; + var controllerObject3D = evt.detail.model; + var self = this; + if (!this.data.model) { + return; + } + + // Store button meshes object to be able to change their colors. + buttonMeshes = this.buttonMeshes = {}; + buttonMeshes.grip = { + left: controllerObject3D.getObjectByName('leftgrip'), + right: controllerObject3D.getObjectByName('rightgrip') + }; + buttonMeshes.menu = controllerObject3D.getObjectByName('menubutton'); + buttonMeshes.system = controllerObject3D.getObjectByName('systembutton'); + buttonMeshes.trackpad = controllerObject3D.getObjectByName('touchpad'); + buttonMeshes.trigger = controllerObject3D.getObjectByName('trigger'); + this.triggerOriginalRotationX = buttonMeshes.trigger.rotation.x; + + // Set default colors. + Object.keys(buttonMeshes).forEach(function (buttonName) { + self.setButtonColor(buttonName, self.data.buttonColor); + }); + + // Offset pivot point. + controllerObject3D.position.copy(INDEX_CONTROLLER_POSITION_OFFSET[this.data.hand]); + controllerObject3D.rotation.copy(INDEX_CONTROLLER_ROTATION_OFFSET[this.data.hand]); + this.el.emit('controllermodelready', { + name: 'valve-index-controlls', + model: this.data.model, + rayOrigin: new THREE.Vector3(0, 0, 0) + }); + }, + onAxisMoved: function (evt) { + emitIfAxesChanged(this, this.mapping.axes, evt); + }, + updateModel: function (buttonName, evtName) { + var color; + var isTouch; + if (!this.data.model) { + return; + } + isTouch = evtName.indexOf('touch') !== -1; + // Don't change color for trackpad touch. + if (isTouch) { + return; + } + + // Update colors. + color = evtName === 'up' ? this.data.buttonColor : this.data.buttonHighlightColor; + this.setButtonColor(buttonName, color); + }, + setButtonColor: function (buttonName, color) { + // TODO: The meshes aren't set up correctly now, skipping for the moment + return; + } +}); + +/***/ }), + +/***/ "./src/components/visible.js": +/*!***********************************!*\ + !*** ./src/components/visible.js ***! + \***********************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); + +/** + * Visibility component. + */ +module.exports.Component = registerComponent('visible', { + schema: { + default: true + }, + update: function () { + this.el.object3D.visible = this.data; + } +}); + +/***/ }), + +/***/ "./src/components/vive-controls.js": +/*!*****************************************!*\ + !*** ./src/components/vive-controls.js ***! + \*****************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var bind = __webpack_require__(/*! ../utils/bind */ "./src/utils/bind.js"); +var trackedControlsUtils = __webpack_require__(/*! ../utils/tracked-controls */ "./src/utils/tracked-controls.js"); +var checkControllerPresentAndSetup = trackedControlsUtils.checkControllerPresentAndSetup; +var emitIfAxesChanged = trackedControlsUtils.emitIfAxesChanged; +var onButtonEvent = trackedControlsUtils.onButtonEvent; +var VIVE_CONTROLLER_MODEL_OBJ_URL = 'https://cdn.aframe.io/controllers/vive/vr_controller_vive.obj'; +var VIVE_CONTROLLER_MODEL_OBJ_MTL = 'https://cdn.aframe.io/controllers/vive/vr_controller_vive.mtl'; +var isWebXRAvailable = (__webpack_require__(/*! ../utils/ */ "./src/utils/index.js").device.isWebXRAvailable); +var GAMEPAD_ID_WEBXR = 'htc-vive'; +var GAMEPAD_ID_WEBVR = 'OpenVR '; + +// Prefix for Gen1 and Gen2 Oculus Touch Controllers. +var GAMEPAD_ID_PREFIX = isWebXRAvailable ? GAMEPAD_ID_WEBXR : GAMEPAD_ID_WEBVR; + +/** + * Button IDs: + * 0 - trackpad + * 1 - trigger (intensity value from 0.5 to 1) + * 2 - grip + * 3 - menu (dispatch but better for menu options) + * 4 - system (never dispatched on this layer) + */ +var INPUT_MAPPING_WEBVR = { + axes: { + trackpad: [0, 1] + }, + buttons: ['trackpad', 'trigger', 'grip', 'menu', 'system'] +}; + +/** + * Button IDs: + * 0 - trigger + * 1 - squeeze + * 2 - touchpad + * 3 - none (dispatch but better for menu options) + * 4 - menu (never dispatched on this layer) + * + * Axis: + * 0 - touchpad x axis + * 1 - touchpad y axis + * Reference: https://github.com/immersive-web/webxr-input-profiles/blob/master/packages/registry/profiles/htc/htc-vive.json + */ +var INPUT_MAPPING_WEBXR = { + axes: { + thumbstick: [0, 1] + }, + buttons: ['trigger', 'grip', 'trackpad', 'none', 'menu'] +}; +var INPUT_MAPPING = isWebXRAvailable ? INPUT_MAPPING_WEBXR : INPUT_MAPPING_WEBVR; + +/** + * Vive controls. + * Interface with Vive controllers and map Gamepad events to controller buttons: + * trackpad, trigger, grip, menu, system + * Load a controller model and highlight the pressed buttons. + */ +module.exports.Component = registerComponent('vive-controls', { + schema: { + hand: { + default: 'left' + }, + buttonColor: { + type: 'color', + default: '#FAFAFA' + }, + // Off-white. + buttonHighlightColor: { + type: 'color', + default: '#22D1EE' + }, + // Light blue. + model: { + default: true + }, + orientationOffset: { + type: 'vec3' + } + }, + mapping: INPUT_MAPPING, + init: function () { + var self = this; + this.controllerPresent = false; + this.lastControllerCheck = 0; + this.onButtonChanged = bind(this.onButtonChanged, this); + this.onButtonDown = function (evt) { + onButtonEvent(evt.detail.id, 'down', self); + }; + this.onButtonUp = function (evt) { + onButtonEvent(evt.detail.id, 'up', self); + }; + this.onButtonTouchEnd = function (evt) { + onButtonEvent(evt.detail.id, 'touchend', self); + }; + this.onButtonTouchStart = function (evt) { + onButtonEvent(evt.detail.id, 'touchstart', self); + }; + this.previousButtonValues = {}; + this.rendererSystem = this.el.sceneEl.systems.renderer; + this.bindMethods(); + }, + update: function () { + var data = this.data; + this.controllerIndex = data.hand === 'right' ? 0 : data.hand === 'left' ? 1 : 2; + }, + play: function () { + this.checkIfControllerPresent(); + this.addControllersUpdateListener(); + }, + pause: function () { + this.removeEventListeners(); + this.removeControllersUpdateListener(); + }, + bindMethods: function () { + this.onModelLoaded = bind(this.onModelLoaded, this); + this.onControllersUpdate = bind(this.onControllersUpdate, this); + this.checkIfControllerPresent = bind(this.checkIfControllerPresent, this); + this.removeControllersUpdateListener = bind(this.removeControllersUpdateListener, this); + this.onAxisMoved = bind(this.onAxisMoved, this); + }, + addEventListeners: function () { + var el = this.el; + el.addEventListener('buttonchanged', this.onButtonChanged); + el.addEventListener('buttondown', this.onButtonDown); + el.addEventListener('buttonup', this.onButtonUp); + el.addEventListener('touchend', this.onButtonTouchEnd); + el.addEventListener('touchstart', this.onButtonTouchStart); + el.addEventListener('model-loaded', this.onModelLoaded); + el.addEventListener('axismove', this.onAxisMoved); + this.controllerEventsActive = true; + }, + removeEventListeners: function () { + var el = this.el; + el.removeEventListener('buttonchanged', this.onButtonChanged); + el.removeEventListener('buttondown', this.onButtonDown); + el.removeEventListener('buttonup', this.onButtonUp); + el.removeEventListener('touchend', this.onButtonTouchEnd); + el.removeEventListener('touchstart', this.onButtonTouchStart); + el.removeEventListener('model-loaded', this.onModelLoaded); + el.removeEventListener('axismove', this.onAxisMoved); + this.controllerEventsActive = false; + }, + /** + * Once OpenVR returns correct hand data in supporting browsers, we can use hand property. + * var isPresent = checkControllerPresentAndSetup(this.el.sceneEl, GAMEPAD_ID_PREFIX, + { hand: data.hand }); + * Until then, use hardcoded index. + */ + checkIfControllerPresent: function () { + var data = this.data; + checkControllerPresentAndSetup(this, GAMEPAD_ID_PREFIX, { + index: this.controllerIndex, + hand: data.hand + }); + }, + injectTrackedControls: function () { + var el = this.el; + var data = this.data; + + // If we have an OpenVR Gamepad, use the fixed mapping. + el.setAttribute('tracked-controls', { + idPrefix: GAMEPAD_ID_PREFIX, + hand: data.hand, + controller: this.controllerIndex, + orientationOffset: data.orientationOffset + }); + + // Load model. + if (!this.data.model) { + return; + } + this.el.setAttribute('obj-model', { + obj: VIVE_CONTROLLER_MODEL_OBJ_URL, + mtl: VIVE_CONTROLLER_MODEL_OBJ_MTL + }); + }, + addControllersUpdateListener: function () { + this.el.sceneEl.addEventListener('controllersupdated', this.onControllersUpdate, false); + }, + removeControllersUpdateListener: function () { + this.el.sceneEl.removeEventListener('controllersupdated', this.onControllersUpdate, false); + }, + onControllersUpdate: function () { + this.checkIfControllerPresent(); + }, + /** + * Rotate the trigger button based on how hard the trigger is pressed. + */ + onButtonChanged: function (evt) { + var button = this.mapping.buttons[evt.detail.id]; + var buttonMeshes = this.buttonMeshes; + var analogValue; + if (!button) { + return; + } + if (button === 'trigger') { + analogValue = evt.detail.state.value; + // Update trigger rotation depending on button value. + if (buttonMeshes && buttonMeshes.trigger) { + buttonMeshes.trigger.rotation.x = -analogValue * (Math.PI / 12); + } + } + + // Pass along changed event with button state, using button mapping for convenience. + this.el.emit(button + 'changed', evt.detail.state); + }, + onModelLoaded: function (evt) { + var buttonMeshes; + var controllerObject3D = evt.detail.model; + var self = this; + if (!this.data.model) { + return; + } + + // Store button meshes object to be able to change their colors. + buttonMeshes = this.buttonMeshes = {}; + buttonMeshes.grip = { + left: controllerObject3D.getObjectByName('leftgrip'), + right: controllerObject3D.getObjectByName('rightgrip') + }; + buttonMeshes.menu = controllerObject3D.getObjectByName('menubutton'); + buttonMeshes.system = controllerObject3D.getObjectByName('systembutton'); + buttonMeshes.trackpad = controllerObject3D.getObjectByName('touchpad'); + buttonMeshes.trigger = controllerObject3D.getObjectByName('trigger'); + + // Set default colors. + Object.keys(buttonMeshes).forEach(function (buttonName) { + self.setButtonColor(buttonName, self.data.buttonColor); + }); + + // Offset pivot point. + controllerObject3D.position.set(0, -0.015, 0.04); + }, + onAxisMoved: function (evt) { + emitIfAxesChanged(this, this.mapping.axes, evt); + }, + updateModel: function (buttonName, evtName) { + var color; + var isTouch; + if (!this.data.model) { + return; + } + isTouch = evtName.indexOf('touch') !== -1; + // Don't change color for trackpad touch. + if (isTouch) { + return; + } + + // Update colors. + color = evtName === 'up' ? this.data.buttonColor : this.data.buttonHighlightColor; + this.setButtonColor(buttonName, color); + }, + setButtonColor: function (buttonName, color) { + var buttonMeshes = this.buttonMeshes; + var rendererSystem = this.rendererSystem; + if (!buttonMeshes) { + return; + } + + // Need to do both left and right sides for grip. + if (buttonName === 'grip') { + buttonMeshes.grip.left.material.color.set(color); + buttonMeshes.grip.right.material.color.set(color); + rendererSystem.applyColorCorrection(buttonMeshes.grip.left.material.color); + rendererSystem.applyColorCorrection(buttonMeshes.grip.right.material.color); + return; + } + buttonMeshes[buttonName].material.color.set(color); + rendererSystem.applyColorCorrection(buttonMeshes[buttonName].material.color); + } +}); + +/***/ }), + +/***/ "./src/components/vive-focus-controls.js": +/*!***********************************************!*\ + !*** ./src/components/vive-focus-controls.js ***! + \***********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var bind = __webpack_require__(/*! ../utils/bind */ "./src/utils/bind.js"); +var trackedControlsUtils = __webpack_require__(/*! ../utils/tracked-controls */ "./src/utils/tracked-controls.js"); +var checkControllerPresentAndSetup = trackedControlsUtils.checkControllerPresentAndSetup; +var emitIfAxesChanged = trackedControlsUtils.emitIfAxesChanged; +var onButtonEvent = trackedControlsUtils.onButtonEvent; +var GAMEPAD_ID_PREFIX = 'HTC Vive Focus'; +var VIVE_FOCUS_CONTROLLER_MODEL_URL = 'https://cdn.aframe.io/controllers/vive/focus-controller/focus-controller.gltf'; + +/** + * Vive Focus controls. + * Interface with Vive Focus controller and map Gamepad events to + * controller buttons: trackpad, trigger + * Load a controller model and highlight the pressed buttons. + */ +module.exports.Component = registerComponent('vive-focus-controls', { + schema: { + hand: { + default: '' + }, + // This informs the degenerate arm model. + buttonTouchedColor: { + type: 'color', + default: '#BBBBBB' + }, + buttonHighlightColor: { + type: 'color', + default: '#7A7A7A' + }, + model: { + default: true + }, + orientationOffset: { + type: 'vec3' + }, + armModel: { + default: true + } + }, + /** + * Button IDs: + * 0 - trackpad + * 1 - trigger + */ + mapping: { + axes: { + trackpad: [0, 1] + }, + buttons: ['trackpad', 'trigger'] + }, + bindMethods: function () { + this.onModelLoaded = bind(this.onModelLoaded, this); + this.onControllersUpdate = bind(this.onControllersUpdate, this); + this.checkIfControllerPresent = bind(this.checkIfControllerPresent, this); + this.removeControllersUpdateListener = bind(this.removeControllersUpdateListener, this); + this.onAxisMoved = bind(this.onAxisMoved, this); + }, + init: function () { + var self = this; + this.onButtonChanged = bind(this.onButtonChanged, this); + this.onButtonDown = function (evt) { + onButtonEvent(evt.detail.id, 'down', self); + }; + this.onButtonUp = function (evt) { + onButtonEvent(evt.detail.id, 'up', self); + }; + this.onButtonTouchStart = function (evt) { + onButtonEvent(evt.detail.id, 'touchstart', self); + }; + this.onButtonTouchEnd = function (evt) { + onButtonEvent(evt.detail.id, 'touchend', self); + }; + this.controllerPresent = false; + this.lastControllerCheck = 0; + this.bindMethods(); + }, + addEventListeners: function () { + var el = this.el; + el.addEventListener('buttonchanged', this.onButtonChanged); + el.addEventListener('buttondown', this.onButtonDown); + el.addEventListener('buttonup', this.onButtonUp); + el.addEventListener('touchstart', this.onButtonTouchStart); + el.addEventListener('touchend', this.onButtonTouchEnd); + el.addEventListener('model-loaded', this.onModelLoaded); + el.addEventListener('axismove', this.onAxisMoved); + this.controllerEventsActive = true; + this.addControllersUpdateListener(); + }, + removeEventListeners: function () { + var el = this.el; + el.removeEventListener('buttonchanged', this.onButtonChanged); + el.removeEventListener('buttondown', this.onButtonDown); + el.removeEventListener('buttonup', this.onButtonUp); + el.removeEventListener('touchstart', this.onButtonTouchStart); + el.removeEventListener('touchend', this.onButtonTouchEnd); + el.removeEventListener('model-loaded', this.onModelLoaded); + el.removeEventListener('axismove', this.onAxisMoved); + this.controllerEventsActive = false; + this.removeControllersUpdateListener(); + }, + checkIfControllerPresent: function () { + checkControllerPresentAndSetup(this, GAMEPAD_ID_PREFIX, this.data.hand ? { + hand: this.data.hand + } : {}); + }, + play: function () { + this.checkIfControllerPresent(); + this.addControllersUpdateListener(); + }, + pause: function () { + this.removeEventListeners(); + this.removeControllersUpdateListener(); + }, + injectTrackedControls: function () { + var el = this.el; + var data = this.data; + el.setAttribute('tracked-controls', { + armModel: data.armModel, + idPrefix: GAMEPAD_ID_PREFIX, + orientationOffset: data.orientationOffset + }); + if (!this.data.model) { + return; + } + this.el.setAttribute('gltf-model', VIVE_FOCUS_CONTROLLER_MODEL_URL); + }, + addControllersUpdateListener: function () { + this.el.sceneEl.addEventListener('controllersupdated', this.onControllersUpdate, false); + }, + removeControllersUpdateListener: function () { + this.el.sceneEl.removeEventListener('controllersupdated', this.onControllersUpdate, false); + }, + onControllersUpdate: function () { + this.checkIfControllerPresent(); + }, + onModelLoaded: function (evt) { + var controllerObject3D = evt.detail.model; + var buttonMeshes; + if (!this.data.model) { + return; + } + buttonMeshes = this.buttonMeshes = {}; + buttonMeshes.trigger = controllerObject3D.getObjectByName('BumperKey'); + buttonMeshes.triggerPressed = controllerObject3D.getObjectByName('BumperKey_Press'); + if (buttonMeshes.triggerPressed) { + buttonMeshes.triggerPressed.visible = false; + } + buttonMeshes.trackpad = controllerObject3D.getObjectByName('TouchPad'); + buttonMeshes.trackpadPressed = controllerObject3D.getObjectByName('TouchPad_Press'); + if (buttonMeshes.trackpadPressed) { + buttonMeshes.trackpadPressed.visible = false; + } + }, + // No analog buttons, only emits 0/1 values + onButtonChanged: function (evt) { + var button = this.mapping.buttons[evt.detail.id]; + if (!button) return; + // Pass along changed event with button state, using button mapping for convenience. + this.el.emit(button + 'changed', evt.detail.state); + }, + onAxisMoved: function (evt) { + emitIfAxesChanged(this, this.mapping.axes, evt); + }, + updateModel: function (buttonName, evtName) { + if (!this.data.model) { + return; + } + this.updateButtonModel(buttonName, evtName); + }, + updateButtonModel: function (buttonName, state) { + var buttonMeshes = this.buttonMeshes; + var pressedName = buttonName + 'Pressed'; + if (!buttonMeshes || !buttonMeshes[buttonName] || !buttonMeshes[pressedName]) { + return; + } + var color; + switch (state) { + case 'down': + color = this.data.buttonHighlightColor; + break; + case 'touchstart': + color = this.data.buttonTouchedColor; + break; + } + if (color) { + buttonMeshes[pressedName].material.color.set(color); + } + buttonMeshes[pressedName].visible = !!color; + buttonMeshes[buttonName].visible = !color; + } +}); + +/***/ }), + +/***/ "./src/components/wasd-controls.js": +/*!*****************************************!*\ + !*** ./src/components/wasd-controls.js ***! + \*****************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var KEYCODE_TO_CODE = (__webpack_require__(/*! ../constants */ "./src/constants/index.js").keyboardevent.KEYCODE_TO_CODE); +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var THREE = __webpack_require__(/*! ../lib/three */ "./src/lib/three.js"); +var utils = __webpack_require__(/*! ../utils/ */ "./src/utils/index.js"); +var bind = utils.bind; +var shouldCaptureKeyEvent = utils.shouldCaptureKeyEvent; +var CLAMP_VELOCITY = 0.00001; +var MAX_DELTA = 0.2; +var KEYS = ['KeyW', 'KeyA', 'KeyS', 'KeyD', 'ArrowUp', 'ArrowLeft', 'ArrowRight', 'ArrowDown']; + +/** + * WASD component to control entities using WASD keys. + */ +module.exports.Component = registerComponent('wasd-controls', { + schema: { + acceleration: { + default: 65 + }, + adAxis: { + default: 'x', + oneOf: ['x', 'y', 'z'] + }, + adEnabled: { + default: true + }, + adInverted: { + default: false + }, + enabled: { + default: true + }, + fly: { + default: false + }, + wsAxis: { + default: 'z', + oneOf: ['x', 'y', 'z'] + }, + wsEnabled: { + default: true + }, + wsInverted: { + default: false + } + }, + init: function () { + // To keep track of the pressed keys. + this.keys = {}; + this.easing = 1.1; + this.velocity = new THREE.Vector3(); + + // Bind methods and add event listeners. + this.onBlur = bind(this.onBlur, this); + this.onContextMenu = bind(this.onContextMenu, this); + this.onFocus = bind(this.onFocus, this); + this.onKeyDown = bind(this.onKeyDown, this); + this.onKeyUp = bind(this.onKeyUp, this); + this.onVisibilityChange = bind(this.onVisibilityChange, this); + this.attachVisibilityEventListeners(); + }, + tick: function (time, delta) { + var data = this.data; + var el = this.el; + var velocity = this.velocity; + if (!velocity[data.adAxis] && !velocity[data.wsAxis] && isEmptyObject(this.keys)) { + return; + } + + // Update velocity. + delta = delta / 1000; + this.updateVelocity(delta); + if (!velocity[data.adAxis] && !velocity[data.wsAxis]) { + return; + } + + // Get movement vector and translate position. + el.object3D.position.add(this.getMovementVector(delta)); + }, + update: function (oldData) { + // Reset velocity if axis have changed. + if (oldData.adAxis !== this.data.adAxis) { + this.velocity[oldData.adAxis] = 0; + } + if (oldData.wsAxis !== this.data.wsAxis) { + this.velocity[oldData.wsAxis] = 0; + } + }, + remove: function () { + this.removeKeyEventListeners(); + this.removeVisibilityEventListeners(); + }, + play: function () { + this.attachKeyEventListeners(); + }, + pause: function () { + this.keys = {}; + this.removeKeyEventListeners(); + }, + updateVelocity: function (delta) { + var acceleration; + var adAxis; + var adSign; + var data = this.data; + var keys = this.keys; + var velocity = this.velocity; + var wsAxis; + var wsSign; + adAxis = data.adAxis; + wsAxis = data.wsAxis; + + // If FPS too low, reset velocity. + if (delta > MAX_DELTA) { + velocity[adAxis] = 0; + velocity[wsAxis] = 0; + return; + } + + // https://gamedev.stackexchange.com/questions/151383/frame-rate-independant-movement-with-acceleration + var scaledEasing = Math.pow(1 / this.easing, delta * 60); + // Velocity Easing. + if (velocity[adAxis] !== 0) { + velocity[adAxis] = velocity[adAxis] * scaledEasing; + } + if (velocity[wsAxis] !== 0) { + velocity[wsAxis] = velocity[wsAxis] * scaledEasing; + } + + // Clamp velocity easing. + if (Math.abs(velocity[adAxis]) < CLAMP_VELOCITY) { + velocity[adAxis] = 0; + } + if (Math.abs(velocity[wsAxis]) < CLAMP_VELOCITY) { + velocity[wsAxis] = 0; + } + if (!data.enabled) { + return; + } + + // Update velocity using keys pressed. + acceleration = data.acceleration; + if (data.adEnabled) { + adSign = data.adInverted ? -1 : 1; + if (keys.KeyA || keys.ArrowLeft) { + velocity[adAxis] -= adSign * acceleration * delta; + } + if (keys.KeyD || keys.ArrowRight) { + velocity[adAxis] += adSign * acceleration * delta; + } + } + if (data.wsEnabled) { + wsSign = data.wsInverted ? -1 : 1; + if (keys.KeyW || keys.ArrowUp) { + velocity[wsAxis] -= wsSign * acceleration * delta; + } + if (keys.KeyS || keys.ArrowDown) { + velocity[wsAxis] += wsSign * acceleration * delta; + } + } + }, + getMovementVector: function () { + var directionVector = new THREE.Vector3(0, 0, 0); + var rotationEuler = new THREE.Euler(0, 0, 0, 'YXZ'); + return function (delta) { + var rotation = this.el.getAttribute('rotation'); + var velocity = this.velocity; + var xRotation; + directionVector.copy(velocity); + directionVector.multiplyScalar(delta); + + // Absolute. + if (!rotation) { + return directionVector; + } + xRotation = this.data.fly ? rotation.x : 0; + + // Transform direction relative to heading. + rotationEuler.set(THREE.MathUtils.degToRad(xRotation), THREE.MathUtils.degToRad(rotation.y), 0); + directionVector.applyEuler(rotationEuler); + return directionVector; + }; + }(), + attachVisibilityEventListeners: function () { + window.oncontextmenu = this.onContextMenu; + window.addEventListener('blur', this.onBlur); + window.addEventListener('focus', this.onFocus); + document.addEventListener('visibilitychange', this.onVisibilityChange); + }, + removeVisibilityEventListeners: function () { + window.removeEventListener('blur', this.onBlur); + window.removeEventListener('focus', this.onFocus); + document.removeEventListener('visibilitychange', this.onVisibilityChange); + }, + attachKeyEventListeners: function () { + window.addEventListener('keydown', this.onKeyDown); + window.addEventListener('keyup', this.onKeyUp); + }, + removeKeyEventListeners: function () { + window.removeEventListener('keydown', this.onKeyDown); + window.removeEventListener('keyup', this.onKeyUp); + }, + onContextMenu: function () { + var keys = Object.keys(this.keys); + for (var i = 0; i < keys.length; i++) { + delete this.keys[keys[i]]; + } + }, + onBlur: function () { + this.pause(); + }, + onFocus: function () { + this.play(); + }, + onVisibilityChange: function () { + if (document.hidden) { + this.onBlur(); + } else { + this.onFocus(); + } + }, + onKeyDown: function (event) { + var code; + if (!shouldCaptureKeyEvent(event)) { + return; + } + code = event.code || KEYCODE_TO_CODE[event.keyCode]; + if (KEYS.indexOf(code) !== -1) { + this.keys[code] = true; + } + }, + onKeyUp: function (event) { + var code; + code = event.code || KEYCODE_TO_CODE[event.keyCode]; + delete this.keys[code]; + } +}); +function isEmptyObject(keys) { + var key; + for (key in keys) { + return false; + } + return true; +} + +/***/ }), + +/***/ "./src/components/windows-motion-controls.js": +/*!***************************************************!*\ + !*** ./src/components/windows-motion-controls.js ***! + \***************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/* global THREE */ +var registerComponent = (__webpack_require__(/*! ../core/component */ "./src/core/component.js").registerComponent); +var bind = __webpack_require__(/*! ../utils/bind */ "./src/utils/bind.js"); +var trackedControlsUtils = __webpack_require__(/*! ../utils/tracked-controls */ "./src/utils/tracked-controls.js"); +var checkControllerPresentAndSetup = trackedControlsUtils.checkControllerPresentAndSetup; +var emitIfAxesChanged = trackedControlsUtils.emitIfAxesChanged; +var onButtonEvent = trackedControlsUtils.onButtonEvent; +var utils = __webpack_require__(/*! ../utils/ */ "./src/utils/index.js"); +var debug = utils.debug('components:windows-motion-controls:debug'); +var warn = utils.debug('components:windows-motion-controls:warn'); +var DEFAULT_HANDEDNESS = (__webpack_require__(/*! ../constants */ "./src/constants/index.js").DEFAULT_HANDEDNESS); +var MODEL_BASE_URL = 'https://cdn.aframe.io/controllers/microsoft/'; +var MODEL_FILENAMES = { + left: 'left.glb', + right: 'right.glb', + default: 'universal.glb' +}; +var isWebXRAvailable = (__webpack_require__(/*! ../utils/ */ "./src/utils/index.js").device.isWebXRAvailable); +var GAMEPAD_ID_WEBXR = 'windows-mixed-reality'; +var GAMEPAD_ID_WEBVR = 'Spatial Controller (Spatial Interaction Source) '; +var GAMEPAD_ID_PATTERN = /([0-9a-zA-Z]+-[0-9a-zA-Z]+)$/; +var GAMEPAD_ID_PREFIX = isWebXRAvailable ? GAMEPAD_ID_WEBXR : GAMEPAD_ID_WEBVR; +var INPUT_MAPPING_WEBVR = { + // A-Frame specific semantic axis names + axes: { + 'thumbstick': [0, 1], + 'trackpad': [2, 3] + }, + // A-Frame specific semantic button names + buttons: ['thumbstick', 'trigger', 'grip', 'menu', 'trackpad'], + // A mapping of the semantic name to node name in the glTF model file, + // that should be transformed by axis value. + // This array mirrors the browser Gamepad.axes array, such that + // the mesh corresponding to axis 0 is in this array index 0. + axisMeshNames: ['THUMBSTICK_X', 'THUMBSTICK_Y', 'TOUCHPAD_TOUCH_X', 'TOUCHPAD_TOUCH_Y'], + // A mapping of the semantic name to button node name in the glTF model file, + // that should be transformed by button value. + buttonMeshNames: { + 'trigger': 'SELECT', + 'menu': 'MENU', + 'grip': 'GRASP', + 'thumbstick': 'THUMBSTICK_PRESS', + 'trackpad': 'TOUCHPAD_PRESS' + }, + pointingPoseMeshName: 'POINTING_POSE' +}; +var INPUT_MAPPING_WEBXR = { + // A-Frame specific semantic axis names + axes: { + 'touchpad': [0, 1], + 'thumbstick': [2, 3] + }, + // A-Frame specific semantic button names + buttons: ['trigger', 'squeeze', 'touchpad', 'thumbstick', 'menu'], + // A mapping of the semantic name to node name in the glTF model file, + // that should be transformed by axis value. + // This array mirrors the browser Gamepad.axes array, such that + // the mesh corresponding to axis 0 is in this array index 0. + axisMeshNames: ['TOUCHPAD_TOUCH_X', 'TOUCHPAD_TOUCH_X', 'THUMBSTICK_X', 'THUMBSTICK_Y'], + // A mapping of the semantic name to button node name in the glTF model file, + // that should be transformed by button value. + buttonMeshNames: { + 'trigger': 'SELECT', + 'menu': 'MENU', + 'squeeze': 'GRASP', + 'thumbstick': 'THUMBSTICK_PRESS', + 'touchpad': 'TOUCHPAD_PRESS' + }, + pointingPoseMeshName: 'POINTING_POSE' +}; +var INPUT_MAPPING = isWebXRAvailable ? INPUT_MAPPING_WEBXR : INPUT_MAPPING_WEBVR; + +/** + * Windows Motion Controller controls. + * Interface with Windows Motion Controller controllers and map Gamepad events to + * controller buttons: trackpad, trigger, grip, menu, thumbstick + * Load a controller model and transform the pressed buttons. + */ +module.exports.Component = registerComponent('windows-motion-controls', { + schema: { + hand: { + default: DEFAULT_HANDEDNESS + }, + // It is possible to have multiple pairs of controllers attached (a pair has both left and right). + // Set this to 1 to use a controller from the second pair, 2 from the third pair, etc. + pair: { + default: 0 + }, + // If true, loads the controller glTF asset. + model: { + default: true + }, + // If true, will hide the model from the scene if no matching gamepad (based on ID & hand) is connected. + hideDisconnected: { + default: true + } + }, + mapping: INPUT_MAPPING, + bindMethods: function () { + this.onModelError = bind(this.onModelError, this); + this.onModelLoaded = bind(this.onModelLoaded, this); + this.onControllersUpdate = bind(this.onControllersUpdate, this); + this.checkIfControllerPresent = bind(this.checkIfControllerPresent, this); + this.onAxisMoved = bind(this.onAxisMoved, this); + }, + init: function () { + var self = this; + var el = this.el; + this.onButtonChanged = bind(this.onButtonChanged, this); + this.onButtonDown = function (evt) { + onButtonEvent(evt.detail.id, 'down', self); + }; + this.onButtonUp = function (evt) { + onButtonEvent(evt.detail.id, 'up', self); + }; + this.onButtonTouchStart = function (evt) { + onButtonEvent(evt.detail.id, 'touchstart', self); + }; + this.onButtonTouchEnd = function (evt) { + onButtonEvent(evt.detail.id, 'touchend', self); + }; + this.onControllerConnected = function () { + self.setModelVisibility(true); + }; + this.onControllerDisconnected = function () { + self.setModelVisibility(false); + }; + this.controllerPresent = false; + this.lastControllerCheck = 0; + this.previousButtonValues = {}; + this.bindMethods(); + + // Cache for submeshes that we have looked up by name. + this.loadedMeshInfo = { + buttonMeshes: null, + axisMeshes: null + }; + + // Pointing poses + this.rayOrigin = { + origin: new THREE.Vector3(), + direction: new THREE.Vector3(0, 0, -1), + createdFromMesh: false + }; + el.addEventListener('controllerconnected', this.onControllerConnected); + el.addEventListener('controllerdisconnected', this.onControllerDisconnected); + }, + addEventListeners: function () { + var el = this.el; + el.addEventListener('buttonchanged', this.onButtonChanged); + el.addEventListener('buttondown', this.onButtonDown); + el.addEventListener('buttonup', this.onButtonUp); + el.addEventListener('touchstart', this.onButtonTouchStart); + el.addEventListener('touchend', this.onButtonTouchEnd); + el.addEventListener('axismove', this.onAxisMoved); + el.addEventListener('model-error', this.onModelError); + el.addEventListener('model-loaded', this.onModelLoaded); + this.controllerEventsActive = true; + }, + removeEventListeners: function () { + var el = this.el; + el.removeEventListener('buttonchanged', this.onButtonChanged); + el.removeEventListener('buttondown', this.onButtonDown); + el.removeEventListener('buttonup', this.onButtonUp); + el.removeEventListener('touchstart', this.onButtonTouchStart); + el.removeEventListener('touchend', this.onButtonTouchEnd); + el.removeEventListener('axismove', this.onAxisMoved); + el.removeEventListener('model-error', this.onModelError); + el.removeEventListener('model-loaded', this.onModelLoaded); + this.controllerEventsActive = false; + }, + checkIfControllerPresent: function () { + checkControllerPresentAndSetup(this, GAMEPAD_ID_PREFIX, { + hand: this.data.hand, + index: this.data.pair, + iterateControllerProfiles: true + }); + }, + play: function () { + this.checkIfControllerPresent(); + this.addControllersUpdateListener(); + }, + pause: function () { + this.removeEventListeners(); + this.removeControllersUpdateListener(); + }, + updateControllerModel: function () { + // If we do not want to load a model, or, have already loaded the model, emit the controllermodelready event. + if (!this.data.model || this.rayOrigin.createdFromMesh) { + this.modelReady(); + return; + } + var sourceUrl = this.createControllerModelUrl(); + this.loadModel(sourceUrl); + }, + /** + * Helper function that constructs a URL from the controller ID suffix, for future proofed + * art assets. + */ + createControllerModelUrl: function (forceDefault) { + // Determine the device specific folder based on the ID suffix + var trackedControlsComponent = this.el.components['tracked-controls']; + var controller = trackedControlsComponent ? trackedControlsComponent.controller : null; + var device = 'default'; + var hand = this.data.hand; + var filename; + if (controller && !window.hasNativeWebXRImplementation) { + // Read hand directly from the controller, rather than this.data, as in the case that the controller + // is unhanded this.data will still have 'left' or 'right' (depending on what the user inserted in to the scene). + // In this case, we want to load the universal model, so need to get the '' from the controller. + hand = controller.hand; + if (!forceDefault) { + var match = controller.id.match(GAMEPAD_ID_PATTERN); + device = match && match[0] || device; + } + } + + // Hand + filename = MODEL_FILENAMES[hand] || MODEL_FILENAMES.default; + + // Final url + return MODEL_BASE_URL + device + '/' + filename; + }, + injectTrackedControls: function () { + var data = this.data; + this.el.setAttribute('tracked-controls', { + idPrefix: GAMEPAD_ID_PREFIX, + controller: data.pair, + hand: data.hand, + armModel: false + }); + this.updateControllerModel(); + }, + addControllersUpdateListener: function () { + this.el.sceneEl.addEventListener('controllersupdated', this.onControllersUpdate, false); + }, + removeControllersUpdateListener: function () { + this.el.sceneEl.removeEventListener('controllersupdated', this.onControllersUpdate, false); + }, + onControllersUpdate: function () { + this.checkIfControllerPresent(); + }, + onModelError: function (evt) { + var defaultUrl = this.createControllerModelUrl(true); + if (evt.detail.src !== defaultUrl) { + warn('Failed to load controller model for device, attempting to load default.'); + this.loadModel(defaultUrl); + } else { + warn('Failed to load default controller model.'); + } + }, + loadModel: function (url) { + // The model is loaded by the gltf-model compoent when this attribute is initially set, + // removed and re-loaded if the given url changes. + this.el.setAttribute('gltf-model', 'url(' + url + ')'); + }, + onModelLoaded: function (evt) { + var rootNode = this.controllerModel = evt.detail.model; + var loadedMeshInfo = this.loadedMeshInfo; + var i; + var meshName; + var mesh; + var meshInfo; + debug('Processing model'); + + // Reset the caches + loadedMeshInfo.buttonMeshes = {}; + loadedMeshInfo.axisMeshes = {}; + + // Cache our meshes so we aren't traversing the hierarchy per frame + if (rootNode) { + // Button Meshes + for (i = 0; i < this.mapping.buttons.length; i++) { + meshName = this.mapping.buttonMeshNames[this.mapping.buttons[i]]; + if (!meshName) { + debug('Skipping unknown button at index: ' + i + ' with mapped name: ' + this.mapping.buttons[i]); + continue; + } + mesh = rootNode.getObjectByName(meshName); + if (!mesh) { + warn('Missing button mesh with name: ' + meshName); + continue; + } + meshInfo = { + index: i, + value: getImmediateChildByName(mesh, 'VALUE'), + pressed: getImmediateChildByName(mesh, 'PRESSED'), + unpressed: getImmediateChildByName(mesh, 'UNPRESSED') + }; + if (meshInfo.value && meshInfo.pressed && meshInfo.unpressed) { + loadedMeshInfo.buttonMeshes[this.mapping.buttons[i]] = meshInfo; + } else { + // If we didn't find the mesh, it simply means this button won't have transforms applied as mapped button value changes. + warn('Missing button submesh under mesh with name: ' + meshName + '(VALUE: ' + !!meshInfo.value + ', PRESSED: ' + !!meshInfo.pressed + ', UNPRESSED:' + !!meshInfo.unpressed + ')'); + } + } + + // Axis Meshes + for (i = 0; i < this.mapping.axisMeshNames.length; i++) { + meshName = this.mapping.axisMeshNames[i]; + if (!meshName) { + debug('Skipping unknown axis at index: ' + i); + continue; + } + mesh = rootNode.getObjectByName(meshName); + if (!mesh) { + warn('Missing axis mesh with name: ' + meshName); + continue; + } + meshInfo = { + index: i, + value: getImmediateChildByName(mesh, 'VALUE'), + min: getImmediateChildByName(mesh, 'MIN'), + max: getImmediateChildByName(mesh, 'MAX') + }; + if (meshInfo.value && meshInfo.min && meshInfo.max) { + loadedMeshInfo.axisMeshes[i] = meshInfo; + } else { + // If we didn't find the mesh, it simply means this axis won't have transforms applied as mapped axis values change. + warn('Missing axis submesh under mesh with name: ' + meshName + '(VALUE: ' + !!meshInfo.value + ', MIN: ' + !!meshInfo.min + ', MAX:' + !!meshInfo.max + ')'); + } + } + this.calculateRayOriginFromMesh(rootNode); + // Determine if the model has to be visible or not. + this.setModelVisibility(); + } + debug('Model load complete.'); + + // Look through only immediate children. This will return null if no mesh exists with the given name. + function getImmediateChildByName(object3d, value) { + for (var i = 0, l = object3d.children.length; i < l; i++) { + var obj = object3d.children[i]; + if (obj && obj['name'] === value) { + return obj; + } + } + return undefined; + } + }, + calculateRayOriginFromMesh: function () { + var quaternion = new THREE.Quaternion(); + return function (rootNode) { + var mesh; + + // Calculate the pointer pose (used for rays), by applying the world transform of th POINTER_POSE node + // in the glTF (assumes that root node is at world origin) + this.rayOrigin.origin.set(0, 0, 0); + this.rayOrigin.direction.set(0, 0, -1); + this.rayOrigin.createdFromMesh = true; + + // Try to read Pointing pose from the source model + mesh = rootNode.getObjectByName(this.mapping.pointingPoseMeshName); + if (mesh) { + var parent = rootNode.parent; + + // We need to read pose transforms accumulated from the root of the glTF, not the scene. + if (parent) { + rootNode.parent = null; + rootNode.updateMatrixWorld(true); + rootNode.parent = parent; + } + mesh.getWorldPosition(this.rayOrigin.origin); + mesh.getWorldQuaternion(quaternion); + this.rayOrigin.direction.applyQuaternion(quaternion); + + // Recalculate the world matrices now that the rootNode is re-attached to the parent. + if (parent) { + rootNode.updateMatrixWorld(true); + } + } else { + debug('Mesh does not contain pointing origin data, defaulting to none.'); + } + + // Emit event stating that our pointing ray is now accurate. + this.modelReady(); + }; + }(), + lerpAxisTransform: function () { + var quaternion = new THREE.Quaternion(); + return function (axis, axisValue) { + var axisMeshInfo = this.loadedMeshInfo.axisMeshes[axis]; + if (!axisMeshInfo) return; + var min = axisMeshInfo.min; + var max = axisMeshInfo.max; + var target = axisMeshInfo.value; + + // Convert from gamepad value range (-1 to +1) to lerp range (0 to 1) + var lerpValue = axisValue * 0.5 + 0.5; + target.setRotationFromQuaternion(quaternion.copy(min.quaternion).slerp(max.quaternion, lerpValue)); + target.position.lerpVectors(min.position, max.position, lerpValue); + }; + }(), + lerpButtonTransform: function () { + var quaternion = new THREE.Quaternion(); + return function (buttonName, buttonValue) { + var buttonMeshInfo = this.loadedMeshInfo.buttonMeshes[buttonName]; + if (!buttonMeshInfo) return; + var min = buttonMeshInfo.unpressed; + var max = buttonMeshInfo.pressed; + var target = buttonMeshInfo.value; + target.setRotationFromQuaternion(quaternion.copy(min.quaternion).slerp(max.quaternion, buttonValue)); + target.position.lerpVectors(min.position, max.position, buttonValue); + }; + }(), + modelReady: function () { + this.el.emit('controllermodelready', { + name: 'windows-motion-controls', + model: this.data.model, + rayOrigin: this.rayOrigin + }); + }, + onButtonChanged: function (evt) { + var buttonName = this.mapping.buttons[evt.detail.id]; + if (buttonName) { + // Update the button mesh transform + if (this.loadedMeshInfo && this.loadedMeshInfo.buttonMeshes) { + this.lerpButtonTransform(buttonName, evt.detail.state.value); + } + + // Only emit events for buttons that we know how to map from index to name + this.el.emit(buttonName + 'changed', evt.detail.state); + } + }, + onAxisMoved: function (evt) { + var numAxes = this.mapping.axisMeshNames.length; + + // Only attempt to update meshes if we have valid data. + if (this.loadedMeshInfo && this.loadedMeshInfo.axisMeshes) { + for (var axis = 0; axis < numAxes; axis++) { + // Update the button mesh transform + this.lerpAxisTransform(axis, evt.detail.axis[axis] || 0.0); + } + } + emitIfAxesChanged(this, this.mapping.axes, evt); + }, + setModelVisibility: function (visible) { + var model = this.el.getObject3D('mesh'); + visible = visible !== undefined ? visible : this.modelVisible; + this.modelVisible = visible; + if (!model) { + return; + } + model.visible = visible; + } +}); + +/***/ }), + +/***/ "./src/constants/index.js": +/*!********************************!*\ + !*** ./src/constants/index.js ***! + \********************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +module.exports = { + AFRAME_INJECTED: 'aframe-injected', + DEFAULT_CAMERA_HEIGHT: 1.6, + DEFAULT_HANDEDNESS: 'right', + keyboardevent: __webpack_require__(/*! ./keyboardevent */ "./src/constants/keyboardevent.js") +}; + +/***/ }), + +/***/ "./src/constants/keyboardevent.js": +/*!****************************************!*\ + !*** ./src/constants/keyboardevent.js ***! + \****************************************/ +/***/ ((module) => { + +module.exports = { + // Tiny KeyboardEvent.code polyfill. + KEYCODE_TO_CODE: { + '38': 'ArrowUp', + '37': 'ArrowLeft', + '40': 'ArrowDown', + '39': 'ArrowRight', + '87': 'KeyW', + '65': 'KeyA', + '83': 'KeyS', + '68': 'KeyD' + } +}; + +/***/ }), + +/***/ "./src/core/a-assets.js": +/*!******************************!*\ + !*** ./src/core/a-assets.js ***! + \******************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/* global customElements */ +var ANode = (__webpack_require__(/*! ./a-node */ "./src/core/a-node.js").ANode); +var bind = __webpack_require__(/*! ../utils/bind */ "./src/utils/bind.js"); +var debug = __webpack_require__(/*! ../utils/debug */ "./src/utils/debug.js"); +var THREE = __webpack_require__(/*! ../lib/three */ "./src/lib/three.js"); +var fileLoader = new THREE.FileLoader(); +var warn = debug('core:a-assets:warn'); + +/** + * Asset management system. Handles blocking on asset loading. + */ +class AAssets extends ANode { + constructor() { + super(); + this.isAssets = true; + this.fileLoader = fileLoader; + this.timeout = null; + } + connectedCallback() { + // Defer if DOM is not ready. + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', this.connectedCallback.bind(this)); + return; + } + this.doConnectedCallback(); + } + doConnectedCallback() { + var self = this; + var i; + var loaded = []; + var mediaEl; + var mediaEls; + var imgEl; + var imgEls; + var timeout; + super.connectedCallback(); + if (!this.parentNode.isScene) { + throw new Error(' must be a child of a .'); + } + + // Wait for s. + imgEls = this.querySelectorAll('img'); + for (i = 0; i < imgEls.length; i++) { + imgEl = fixUpMediaElement(imgEls[i]); + loaded.push(new Promise(function (resolve, reject) { + // Set in cache because we won't be needing to call three.js loader if we have. + // a loaded media element. + THREE.Cache.add(imgEls[i].getAttribute('src'), imgEl); + imgEl.onload = resolve; + imgEl.onerror = reject; + })); + } + + // Wait for